<?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: Max von Hippel</title>
    <description>The latest articles on DEV Community by Max von Hippel (@maxvonhippel).</description>
    <link>https://dev.to/maxvonhippel</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%2F21333%2Fe80ac421-c8fd-4c16-a9db-95ef6032c700.jpg</url>
      <title>DEV Community: Max von Hippel</title>
      <link>https://dev.to/maxvonhippel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxvonhippel"/>
    <language>en</language>
    <item>
      <title>Automated attack synthesis by extracting protocol FSMs from RFCs</title>
      <dc:creator>Max von Hippel</dc:creator>
      <pubDate>Wed, 09 Feb 2022 19:50:01 +0000</pubDate>
      <link>https://dev.to/maxvonhippel/automated-attack-synthesis-by-extracting-protocol-fsms-from-rfcs-1dck</link>
      <guid>https://dev.to/maxvonhippel/automated-attack-synthesis-by-extracting-protocol-fsms-from-rfcs-1dck</guid>
      <description>&lt;p&gt;Certain automated attack discovery tools, such as &lt;a href="https://github.com/RFCNLP/RFCNLP-korg" rel="noopener noreferrer"&gt;🎹KORG&lt;/a&gt;, &lt;a href="https://github.com/samueljero/snake" rel="noopener noreferrer"&gt;🐍SNAKE&lt;/a&gt;, or &lt;a href="https://github.com/samueljero/TCPwn" rel="noopener noreferrer"&gt;🧰TCPwn&lt;/a&gt;, are designed specifically to ensure that network protocols operate correctly and securely. Such tools generally require a formal representation of the protocol, e.g., a &lt;a href="https://en.wikipedia.org/wiki/Finite-state_machine" rel="noopener noreferrer"&gt;finite state machine (FSM)&lt;/a&gt;, as well as a formal description of message formats and correctness properties.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;TCP FSM&lt;/th&gt;
&lt;th&gt;DCCP FSM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7f9ij6y8yik7jkldzex.png" alt="TCP FSM" width="800" height="819"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs51mu5cymefl27y5xx57.png" alt="DCCP FSM" width="800" height="816"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Formal protocol specifications can be extracted from two sources: implementations or textual descriptions.  &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://github.com/torvalds/linux/blob/fc02cb2b37fe2cbf1d3334b9f0f0eab9431766c4/net/dccp/dccp.h" rel="noopener noreferrer"&gt;DCCP Implementation&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc4340" rel="noopener noreferrer"&gt;DCCP Description&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxyataqdwkv6yba6vemz.png" alt="DCCP implementation from linux kernel" width="800" height="824"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzl7g5ci56056ykjzqhld.png" alt="DCCP RFC textual description snippet" width="800" height="563"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Many prior works extracted FSMs, message formats, or correctness properties from protocol implementations.  For example, &lt;a href="https://sites.cs.ucsb.edu/~chris/research/doc/oakland09_prospex.pdf" rel="noopener noreferrer"&gt;🤖Prospex&lt;/a&gt; extracted state machines from implementations by running them and examining their network traces.  We are interested in the alternative approach of extracting protocol specifications from textual descriptions.&lt;/p&gt;

&lt;p&gt;Network protocols are usually described prosaically in plain-text English-language documents, such as the &lt;a href="https://www.ietf.org/" rel="noopener noreferrer"&gt;IETF&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/List_of_RFCs" rel="noopener noreferrer"&gt;"Request For Comments"&lt;/a&gt; documents, or RFCs.  &lt;a href="https://arxiv.org/pdf/1810.04755.pdf" rel="noopener noreferrer"&gt;In prior work&lt;/a&gt;, we showed how to extract protocol message formats from RFC documents, with &lt;a href="https://github.com/samueljero/snake" rel="noopener noreferrer"&gt;grammar-based fuzzing&lt;/a&gt; as our motivating use-case.  However, implementing an RFC FSM also requires significant human labor and expertise.  &lt;/p&gt;

&lt;p&gt;In this work, we try to alleviate this human burden by partially automating the process of FSM extraction, with &lt;a href="https://arxiv.org/pdf/2004.01220.pdf" rel="noopener noreferrer"&gt;attacker synthesis&lt;/a&gt; as our motivating use-case.  Our paper will appear in the &lt;a href="https://www.ieee-security.org/TC/SP2022/" rel="noopener noreferrer"&gt;2022 IEEE S&amp;amp;P&lt;/a&gt;, and our code is &lt;a href="https://github.com/RFCNLP" rel="noopener noreferrer"&gt;open-source&lt;/a&gt; and &lt;a href="https://github.com/RFCNLP#reproduce-our-results" rel="noopener noreferrer"&gt;reproducible&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcnlp.pdf" rel="noopener noreferrer"&gt;Preprint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcnlp.bib" rel="noopener noreferrer"&gt;BibTex&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;p&gt;In order to extract an FSM from a protocol RFC, we need to first &lt;em&gt;read&lt;/em&gt; the protocol RFC.  But what does &lt;em&gt;reading the RFC&lt;/em&gt; mean, exactly, in an automated context?  In our work, it meant analyzing the RFC document using &lt;a href="https://en.wikipedia.org/wiki/Natural_language_processing" rel="noopener noreferrer"&gt;natural language processing&lt;/a&gt;, a sub-field of AI concerned with interpreting human language.  This approach came with some built-in challenges.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Defining the Problem.&lt;/strong&gt;  Traditional NLP semantic parsing studies methods for translating natural language into a complete formal representation.  However, RFCs &lt;em&gt;do not&lt;/em&gt; contain "canonical" or "reference" FSMs.  They have mistakes, omissions, and ambiguities which are solved as-needed by human experts.  Even in theory, there is no complete one-to-one mapping from RFCs to FSMs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choosing an NLP Approach.&lt;/strong&gt;  Many off-the-shelf NLP tools exist, typically trained on newswire text.  But when such tools are applied to technical domains their performance degrades substantially.  Meanwhile, training rule-based systems from scratch requires significant human effort to label the data, and will yield poor results on RFCs because different RFC documents define variables, constraints, and temporal behaviors totally differently.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Our Approach
&lt;/h2&gt;

&lt;p&gt;First, we learn a large-scale word representation for technical language using off-the-shelf tools.  Second, we define and learn protocol-independent information from RFCs, using focused zero-shot learning to adapt to new, unobserved protocol documents without re-training.  Third, we use a rule-based mapping from the protocol-independent information to FSMs.  Fourth, we show how the resulting FSMs can then be used for attacker synthesis - although notice that these FSMs could alternatively be used for other applications, such as grammar-based fuzzing.  Let's go over each of these steps in detail below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qs9n2oxopdixhp8be90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qs9n2oxopdixhp8be90.png" alt="Overview of our approach" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Learning a Large-Scale Word Representation
&lt;/h3&gt;

&lt;p&gt;We collect a corpus of RFC-related documents such as &lt;a href="https://stackoverflow.com/search?q=tcp" rel="noopener noreferrer"&gt;technical forums&lt;/a&gt;, &lt;a href="https://dev.to/maxvonhippel/automated-attacker-synthesis-for-distributed-protocols-45mn"&gt;blogs&lt;/a&gt;, &lt;a href="https://arxiv.org/abs/2004.01220" rel="noopener noreferrer"&gt;research papers&lt;/a&gt;, and &lt;a href="https://datatracker.ietf.org/doc/html/rfc793" rel="noopener noreferrer"&gt;specification documents&lt;/a&gt;. We exploit these documents to learn a &lt;a href="https://en.wikipedia.org/wiki/Word_embedding" rel="noopener noreferrer"&gt;distributed word representation&lt;/a&gt;, also known as an embedding model, for technical language.  In particular, we use a &lt;a href="https://pypi.org/project/bert-embedding/" rel="noopener noreferrer"&gt;BERT embedding model&lt;/a&gt;, pre-trained using the masked language model and the next sentence prediction objective using networking data.  This process does not require any manual annotation!&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Zero-Shot Protocol Extraction
&lt;/h3&gt;

&lt;p&gt;Once we have this representation, we turn our attention to learning a model to extract information regarding an FSM from its RFC. Specifically, we want to structurally annotate the protocol RFC, so that we know precisely which parts of the text describe different states, transitions, variables, errors, etc. in the protocol logic.  To do this, we define a grammar that describes a higher-level abstraction of the structure of a general FSM for network protocols, as well as the structure of the RFC document describing the FSM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool      ::= true | false
type      ::= send | receive | issue
def-tag   ::= def_state | def_var | def_event
ref-state ::= ref_state id="##"
ref-event ::= ref_event id="##" type="type"
ref-tag   ::= ref-event | ref-state
def-atom  ::= &amp;lt;def-tag&amp;gt;engl&amp;lt;/def-tag&amp;gt;
sm-atom   ::= &amp;lt;ref-tag&amp;gt;engl&amp;lt;/ref-tag&amp;gt; | engl
sm-tag    ::= trigger | variable | error | timer
act-atom  ::= &amp;lt;arg&amp;gt;sm-atom&amp;lt;/arg&amp;gt; | sm-atom
act-struct::= act-struct | act-struct act-atom
trn-arg   ::= arg_source | arg_target | arg_inter
trn-atom  ::= &amp;lt;trn-arg&amp;gt;sm-atom&amp;lt;trn-arg&amp;gt; | sm-atom
trn-struct::= trn-struct | trn-struct trn-atom
ctl-atom  ::= &amp;lt;sm-tag&amp;gt;sm-atom&amp;lt;/sm-tag&amp;gt;
           | &amp;lt;action type="type"&amp;gt;act-struct&amp;lt;/action&amp;gt;
           | &amp;lt;transition&amp;gt;trn-struct&amp;lt;/transition&amp;gt;
           | sm-atom
ctl-struct::= ctl-atom | ctl-struct ctl-atom
ctl-rel   ::= relevant=bool
control   ::= &amp;lt;control ctl-rel&amp;gt;ctl-struct&amp;lt;/control&amp;gt;
e         ::= control | ctl-atom | def-atom | e_0 e_1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The grammar is general-purpose and intended to support any network protocol.  At a high level, it consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Definition tags&lt;/u&gt;, used to define states, transitions, etc.;&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Reference tags&lt;/u&gt;, used to observe mentions of previously defined data;&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;State Machine tags&lt;/u&gt;, used to track states and transitions; and&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Control flow tags&lt;/u&gt;, used to record the syntactic structure of the RFC document.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, consider the following snippet from the &lt;a href="https://datatracker.ietf.org/doc/html/rfc4340" rel="noopener noreferrer"&gt;Datagram Congestion Control Protocol RFC&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The client leaves the REQUEST state for PARTOPEN when it receives a DCCP-Response from the server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can annotate this snippet like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7wlavzskod0l7w1kzffu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7wlavzskod0l7w1kzffu.png" alt="Diagram of snippet annotation" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we know &lt;em&gt;where to look&lt;/em&gt; in the RFC in order to find certain information (states, transitions, events, etc.).  We call this annotated version of the RFC an "intermediate representation".  For full details refer to Section III in &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcnlp.pdf" rel="noopener noreferrer"&gt;our paper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Annotating the RFC document by hand is almost as time-intensive as manually deriving the protocol FSM.  Clearly, annotation should be automated!  We experimented with several state-of-the-art NLP algorithms for this task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LinearCRF&lt;/code&gt; - a &lt;a href="https://liyanxu.blog/2021/02/20/overview-of-conditional-random-field-crf/" rel="noopener noreferrer"&gt;linear-chain conditional random fields model&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NeuralCRF&lt;/code&gt; - a &lt;a href="https://huggingface.co/docs/transformers/model_doc/bert" rel="noopener noreferrer"&gt;BERT&lt;/a&gt; encoder enhanced with a Bidirectional &lt;a href="https://colah.github.io/posts/2015-08-Understanding-LSTMs/" rel="noopener noreferrer"&gt;LSTM&lt;/a&gt; &lt;a href="https://homepages.inf.ed.ac.uk/csutton/publications/crftut-fnt.pdf" rel="noopener noreferrer"&gt;CRF&lt;/a&gt; layer;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LinearCRF+R&lt;/code&gt; - like &lt;code&gt;LinearCRF&lt;/code&gt; but with some heuristic post-processing rules; and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NeuralCRF+R&lt;/code&gt; - like &lt;code&gt;NeuralCRF&lt;/code&gt; but with those same heuristic post-processing rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;LinearCRF&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;NeuralCRF&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Froew5vpov1xvs7yrbofc.png" alt="LinearCRF" width="800" height="430"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmsorq8n7e6ol1zdmphci.png" alt="NeuralCRF" width="800" height="540"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We evaluate the algorithms on the &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcs-original/BGPv4.txt" rel="noopener noreferrer"&gt;BGPv4&lt;/a&gt;, &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcs-original/DCCP.txt" rel="noopener noreferrer"&gt;DCCP&lt;/a&gt;, &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcs-original/LTP.txt" rel="noopener noreferrer"&gt;LTP&lt;/a&gt;, &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcs-original/PPTP.txt" rel="noopener noreferrer"&gt;PPTP&lt;/a&gt;, &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcs-original/SCTP.txt" rel="noopener noreferrer"&gt;SCTP&lt;/a&gt;, and &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcs-original/TCP.txt" rel="noopener noreferrer"&gt;TCP&lt;/a&gt; RFCs, in Section VIII (a) of &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcnlp.pdf" rel="noopener noreferrer"&gt;our paper&lt;/a&gt;.  Generally, we find that the neural models outperform the linear ones.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Protocol State Machine Extraction
&lt;/h3&gt;

&lt;p&gt;Suppose we're studying the DCCP RFC, and we've produced its intermediary representation either by hand or using &lt;code&gt;LinearCRF&lt;/code&gt;, &lt;code&gt;NeuralCRF&lt;/code&gt;, &lt;code&gt;LinearCRF+R&lt;/code&gt;, or &lt;code&gt;NeuralCRF+R&lt;/code&gt;.  Now that we know &lt;em&gt;where to look&lt;/em&gt; in order to read the RFC, it's time to extract an FSM.  Recall that an FSM consists of &lt;em&gt;states&lt;/em&gt; &lt;code&gt;s ∈ S&lt;/code&gt;, some kind of events &lt;code&gt;e ∈ E&lt;/code&gt;, and transitions &lt;code&gt;t ∈ S x E x S&lt;/code&gt;.  We take the stance that there are four kinds of events: &lt;em&gt;timeouts&lt;/em&gt;, &lt;em&gt;epsilon-transitions&lt;/em&gt; (like &lt;code&gt;noop&lt;/code&gt;s), &lt;em&gt;send-events&lt;/em&gt;, and &lt;em&gt;receive-events&lt;/em&gt;.  &lt;/p&gt;

&lt;p&gt;Luckily, all of this data is explicitly labeled in the intermediary representation!  We just need to assemble it all into an extracted FSM.  Our algorithm to do exactly that is described in (a) Section VI and (b) Algorithm &lt;code&gt;ExtractTran&lt;/code&gt; in the Appendix of &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcnlp.pdf" rel="noopener noreferrer"&gt;our paper&lt;/a&gt;.  You can also read the actual open-source code &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/nlp2promela/xmlUtils.py" rel="noopener noreferrer"&gt;here&lt;/a&gt;.  At a high level, we do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;code&gt;def_state&lt;/code&gt;s to determine the FSM states&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;transition&lt;/code&gt;s to determine the transitions; for each one, search the closest &lt;code&gt;control&lt;/code&gt; block for &lt;code&gt;ref_state&lt;/code&gt;s to determine where the transition begins and ends, and &lt;code&gt;ref_event&lt;/code&gt;s to determine what exactly occurs during the transition.
In the example from before, the correct extracted transition would be:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REQUEST --- rcv(DCCP-Response) --&amp;gt; PARTOPEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the TCP and DCCP FSMs extracted by the &lt;code&gt;LinearCRF+R&lt;/code&gt; and &lt;code&gt;NeuralCRF+R&lt;/code&gt; NLP algorithms in the Appendix of &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcnlp.pdf" rel="noopener noreferrer"&gt;our paper&lt;/a&gt;.  In that same Appendix, we also give "Gold FSMs", which are extracted from RFCs that are annotated by hand.  Mistakes in the Gold FSMs stem from issues in our extraction algorithm, or intrinsic ambiguities in the RFC text.  We give a detailed case-by-case analysis of such mistakes for the NLP-extracted TCP and DCCP FSMs &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/tutorials/detailed.FSM.error.analysis.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Attacker Synthesis
&lt;/h3&gt;

&lt;p&gt;Finally, we get to the attacker synthesis.  Note that attacker synthesis is just one representative protocol analysis technique that uses a protocol FSM.  We used the attacker synthesis tool &lt;a href="https://github.com/maxvonhippel/AttackerSynthesis" rel="noopener noreferrer"&gt;🎹KORG&lt;/a&gt;.  Since KORG was designed for perfect, hand-written FSMs, we had to modify it slightly to support imperfect FSMs like those we can extract from RFCs.  Our modified version is available &lt;a href="https://github.com/RFCNLP/RFCNLP-korg" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case Studies
&lt;/h3&gt;

&lt;p&gt;We use TCP and DCCP as case studies.  For each protocol, we craft four hand-written correctness properties, which we feed to KORG in conjunction with the FSM.  Our results are given in TABLE V and discussed in Section VIII. B of &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcnlp.pdf" rel="noopener noreferrer"&gt;our paper&lt;/a&gt;.  The &lt;em&gt;TL;DR&lt;/em&gt; is that using the NLP-derived FSMs, we find one attack against TCP, which we confirm using a hand-written TCP FSM, and we find numerous attacks against DCCP, of which we confirm some but not all using a hand-written DCCP FSM.  Here are some of those confirmed attacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attack #32 discovered using TCP property 1 and the &lt;code&gt;LinearCRF+R&lt;/code&gt; TCP FSM injects a single &lt;code&gt;ACK&lt;/code&gt; to peer 2, causing a desynchronization between the peers which can eventually lead to a half-open connection, which should be impossible.&lt;/li&gt;
&lt;li&gt;Attack #96 discovered using DCCP property 2 and the &lt;code&gt;NeuralCRF+R&lt;/code&gt; DCCP FSM performs various useless network operations before spoofing each peer in order to guide the other into &lt;code&gt;CLOSE_REQ&lt;/code&gt;.  The two peers should never both be in &lt;code&gt;CLOSE_REQ&lt;/code&gt; at once.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Our work is exciting, because we take a first step toward automatically extracting FSMs (i.e. &lt;em&gt;code&lt;/em&gt;) from RFCs (i.e. &lt;em&gt;text&lt;/em&gt;).  But it's also limited: the FSMs are imperfect, with missing or incorrect transitions, and we still have to write the correctness properties by hand.  We have ideas for how to improve on our technique, which we discuss in Section X (Limitations) of &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/rfcnlp.pdf" rel="noopener noreferrer"&gt;our paper&lt;/a&gt;.  In the mean time, our code is &lt;a href="https://github.com/RFCNLP/RFCNLP/" rel="noopener noreferrer"&gt;open source&lt;/a&gt; and &lt;a href="https://github.com/RFCNLP#reproduce-our-results" rel="noopener noreferrer"&gt;reproducible&lt;/a&gt;.  We also provide a detailed &lt;a href="https://github.com/RFCNLP/RFCNLP/blob/main/tutorials/attacker.synthesis.md" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt; on how to use our software.&lt;/p&gt;

</description>
      <category>fm</category>
      <category>nlp</category>
      <category>rfc</category>
      <category>security</category>
    </item>
    <item>
      <title>PL Tutorial for Sean</title>
      <dc:creator>Max von Hippel</dc:creator>
      <pubDate>Fri, 07 Aug 2020 22:21:21 +0000</pubDate>
      <link>https://dev.to/maxvonhippel/pl-tutorial-for-sean-p6</link>
      <guid>https://dev.to/maxvonhippel/pl-tutorial-for-sean-p6</guid>
      <description>&lt;p&gt;This is a brief and informal overview of a few useful topics in programming languages and theory of computation.  I am writing this to share some basic concepts with my friend Sean, but figured I might as well put it online in case other people find it interesting.  I am not an expert on these topics and so might make some mistakes.  If you notice a mistake, please say so in the comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  BNF
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;grammar&lt;/strong&gt; is some formal rule that (perhaps inductively) generates or describes all the vocabulary in a language.  The least interesting way to do this is to literally write out all the words, as in, &lt;code&gt;N_3 = { 0, 1, 2 }&lt;/code&gt;, but this won't work when we have infinitely large languages.  For example, you can't realistically write out every single valid program in the Python programming language.  This is where BNF comes in.  BNF is best explained via an example.  The human genome consists of cytosine (&lt;code&gt;C&lt;/code&gt;), guanine (&lt;code&gt;G&lt;/code&gt;), adenine (&lt;code&gt;A&lt;/code&gt;), and thymine (&lt;code&gt;T&lt;/code&gt;) molecules super-glued together.  (Sorry Sophia, I am about to massacre the biology.)  So, a BNF grammar for the terms &lt;code&gt;e&lt;/code&gt; (that is, the words of the language) of DNA would look something 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;e ::= e_0 e_1 | A | C | T | G
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;::=&lt;/code&gt; means "is defined to be" and the &lt;code&gt;|&lt;/code&gt; means "or".  Obviously &lt;code&gt;e_0&lt;/code&gt; and &lt;code&gt;e_1&lt;/code&gt; are inductively defined as instances of &lt;code&gt;e&lt;/code&gt;, so an example of the term &lt;code&gt;e_0 e_1&lt;/code&gt; would be &lt;code&gt;T G&lt;/code&gt;.  But another example would be &lt;code&gt;A T G&lt;/code&gt;, where &lt;code&gt;e_0&lt;/code&gt; is &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;e_1&lt;/code&gt; is &lt;code&gt;T G&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to do anything fancier than my DNA example, you need more tools, e.g., contexts.  I won't get into that in this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Untyped Lambda Calculus
&lt;/h2&gt;

&lt;p&gt;The grammar for the untyped lambda calculus is as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;e ::= λx.e | x | e_0 e_1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some more complexities that I won't get into right now, which basically boil down to your decisions about order of operations.  If you want to know more, google "call by value versus call by name".  For now, it suffices to observe that you can easily construct arbitrary computations using the lambda calculus.  The basic idea is that &lt;code&gt;λx.e&lt;/code&gt; is the function that takes as input &lt;code&gt;x&lt;/code&gt; and returns &lt;code&gt;e&lt;/code&gt;.  So the identity function is &lt;code&gt;id = λx.x&lt;/code&gt;, and the concatenation function is &lt;code&gt;cat = λx.λy.xy&lt;/code&gt;.  See what I did there?  You can get the equivalent of &lt;code&gt;f(x, y)&lt;/code&gt; by writing &lt;code&gt;λx.λy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you take the convention that &lt;code&gt;true = λt.λf.t&lt;/code&gt; and &lt;code&gt;false = λt.λf.f&lt;/code&gt; then you can easily reproduce all the basics of boolean algebra.  &lt;a href="https://blog.brunobonacci.com/2017/10/08/lambda-calculus-and-boolean-logic/" rel="noopener noreferrer"&gt;For more see here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There remains one more important thing for me to convince you, namely, that lambda calc equations need not terminate.  Take the following famous example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;omega = (λx.xx)(λx.xx)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviously this can't be reduced.  Observe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f = (λx.xx)
g = (λx.xx)
then omega = f g
           = (λx.xx) g
           = g g 
           = (λx.xx)(λx.xx)
           = omega
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this we conclude that the untyped lambda calculus can do all the basic boolean logic and can also do things that never terminate.  With a bit more bit-crunching you can show it's actually Turing Complete.  In fact I believe it's the smallest possible Turing Complete language.&lt;/p&gt;

&lt;p&gt;For convenience we usually assume some basic tools like &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, etc. so that we can write things like &lt;code&gt;plus = λx.λy.x+y&lt;/code&gt; or &lt;code&gt;++ = λx.x+1&lt;/code&gt;, etc.  Since we can do all boolean algebra, we can build these tools in the same we way build our MIPS or X86 CPUs in Computer Architecture as undergrads (with ripple adders, etc.).&lt;/p&gt;

&lt;h2&gt;
  
  
  STLC
&lt;/h2&gt;

&lt;p&gt;The STLC is the simply typed lambda calculus.  It's not too difficult.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;B ::= some types you are interested in, e.g., Int, Bool, whatever floats your boat ...
t ::= t -&amp;gt; t | B
e ::= x | λx:t.e | e_0 e_1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important observation is that now instead of writing &lt;code&gt;λx.e&lt;/code&gt; to mean "the function with input &lt;code&gt;x&lt;/code&gt; and output &lt;code&gt;e&lt;/code&gt;", we write &lt;code&gt;λx:t.e&lt;/code&gt; to mean "the function with input &lt;code&gt;x&lt;/code&gt; of type &lt;code&gt;t&lt;/code&gt; and output &lt;code&gt;e&lt;/code&gt;."  Then just derive the output type from the input type and the form of &lt;code&gt;e&lt;/code&gt;, and you have all the expressive power of a function &lt;code&gt;f : t --&amp;gt; type(e)&lt;/code&gt; defined by &lt;code&gt;x |-&amp;gt; e&lt;/code&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Proofs
&lt;/h2&gt;

&lt;p&gt;Generally in PL proofs are written in tree form&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assumptions
-----------(deriving rule)
conclusion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as opposed to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assume assumptions
then by deriving rule
conclusion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, suppose I want to prove that &lt;code&gt;omega&lt;/code&gt; reduces to &lt;code&gt;omega&lt;/code&gt;.  I might have a reducing rule like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----------------(reducing-rule)
(λx.e)z --&amp;gt; e[z/x]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we take the usual convention that &lt;code&gt;e[z/x]&lt;/code&gt; means "replace every free occurence of &lt;code&gt;x&lt;/code&gt; in &lt;code&gt;e&lt;/code&gt; with &lt;code&gt;z&lt;/code&gt;."  For example, &lt;code&gt;(λx.x+λx.x)[z/x] = (λx.x+λx.x)&lt;/code&gt;, because all the &lt;code&gt;x&lt;/code&gt;s are bounded whereas &lt;code&gt;(x(λx.x))[z/x] = z(λx.x)&lt;/code&gt;, because the first &lt;code&gt;x&lt;/code&gt; was not bounded.  Bounding works in the same way it would with quantifiers like Ɐ.&lt;/p&gt;

&lt;p&gt;In this case with our &lt;code&gt;reducing-rule&lt;/code&gt; the proof of &lt;code&gt;omega -&amp;gt; omega&lt;/code&gt; could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;----------------------(reducing-rule)    --------------------(some-var-replacement-rule)
(λx.xx)(λx.xx) --&amp;gt; (xx)[(λx.xx)/x]        (xx)[(λx.xx)/x] = omega
--------------------------------------------------(some-modus-ponens-ish-rule)
omega -&amp;gt; omega
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pi Calculus, Mu Calculus, etc.
&lt;/h2&gt;

&lt;p&gt;There are various other calculi exactly equal in power to the lambda calculus that rely on fixed-point equations.  A fixed-point equation is anything of the form&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x = f(x)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, the fixed-point equation &lt;code&gt;x = x^2&lt;/code&gt; has solutions &lt;code&gt;x = { 0, 1 }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In a kind of obvious way, all recursive functions can be described as fixed-point equations, where the equation has a solution for a given input iff the function would eventually terminate for that input, in which case the terminating value is a solution to the equation.&lt;/p&gt;

&lt;p&gt;I won't explain the Pi and Mu calculi here but you can easily learn them if you want to ... the important thing is just understanding they rely on this basic concept.&lt;/p&gt;

&lt;h2&gt;
  
  
  Languages and Automata
&lt;/h2&gt;

&lt;p&gt;An important idea to understand is that there is a relationship between languages and automata.  Just to illustrate this idea let &lt;code&gt;L&lt;/code&gt; be the language generated by the following grammar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;e ::= x | e_0 LET'S GO e_1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So example sentences include &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;x LET'S GO x LET'S GO x LET'S GO x&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;We can just as easily represent this with an automaton.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      x 
--&amp;gt;(s_0)------&amp;gt;(s_1)
    ^            |          
    |____________|
      LET'S GO
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The transitions are labeled, and if you trace any sequence of transitions with your finger and write down the in-order labels, you should get back something generated by the grammar, unless I made a stupid mistake.&lt;/p&gt;

&lt;p&gt;For more on this, see JE Pin's work and book.&lt;/p&gt;

</description>
      <category>pl</category>
      <category>lambda</category>
      <category>pi</category>
      <category>grammar</category>
    </item>
    <item>
      <title>Automated Attacker Synthesis for Distributed Protocols</title>
      <dc:creator>Max von Hippel</dc:creator>
      <pubDate>Tue, 23 Jun 2020 04:07:39 +0000</pubDate>
      <link>https://dev.to/maxvonhippel/automated-attacker-synthesis-for-distributed-protocols-45mn</link>
      <guid>https://dev.to/maxvonhippel/automated-attacker-synthesis-for-distributed-protocols-45mn</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;Distributed protocols are &lt;em&gt;complicated&lt;/em&gt; and &lt;em&gt;important&lt;/em&gt;.  They are &lt;em&gt;complicated&lt;/em&gt; because they require coordination between distributed components to achieve a goal, often in the presence of bugs, faults, and attacks.  They are &lt;em&gt;important&lt;/em&gt; because of the goals they achieve, e.g., &lt;a href="https://www.torproject.org/" rel="noopener noreferrer"&gt;anonymously accessing the web&lt;/a&gt;, or &lt;a href="https://twitter.com/futurepaul/status/1273234983138754560?s=20" rel="noopener noreferrer"&gt;supporting private and spam-free messaging&lt;/a&gt;.  &lt;strong&gt;Vulnerabilities arise from protocol complexity, and matter because of protocol importance.&lt;/strong&gt;  In this work, we &lt;em&gt;automatically synthesize attackers against distributed protocols&lt;/em&gt;, in order to exploit complex logic flaws that humans tend not to notice.&lt;/p&gt;

&lt;p&gt;Citation for &lt;a href="https://arxiv.org/abs/2004.01220" rel="noopener noreferrer"&gt;arXiv preprint&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@article{von2020automated,
  title={Automated Attacker Synthesis for Distributed Protocols},
  author={von Hippel, Max and Vick, Cole and Tripakis, Stavros and Nita-Rotaru, Cristina},
  journal={arXiv preprint arXiv:2004.01220},
  year={2020}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this blog post, I will play &lt;em&gt;fast and loose&lt;/em&gt; with the mathematics, and skip details, in order to efficiently communicate the principal idea of our project.  In doing so, I follow the esteemed footsteps of &lt;a href="https://github.com/hmemcpy/milewski-ctfp-pdf/blob/fb7962437c8d47d34a236d77620db14311ceee9f/src/content/0.0/preface.tex#L50" rel="noopener noreferrer"&gt;Bartosz Milewski&lt;/a&gt;.  For monotonically more formal versions of this material, refer to &lt;a href="https://link.springer.com/chapter/10.1007/978-3-030-54549-9_9" rel="noopener noreferrer"&gt;my SafeComp 2020 presentation&lt;/a&gt;, our &lt;a href="https://link.springer.com/chapter/10.1007/978-3-030-54549-9_9" rel="noopener noreferrer"&gt;SafeComp 2020 paper&lt;/a&gt;, or the &lt;a href="https://arxiv.org/abs/2004.01220" rel="noopener noreferrer"&gt;arXiv preprint&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pseudo-Formal Problem Statement
&lt;/h2&gt;

&lt;p&gt;Imagine a harbor full of ships and boats.  &lt;a href="https://www.ctga.ox.ac.uk/publications/cybersecurity-and-age-privateering-historical-analogy" rel="noopener noreferrer"&gt;There are pirate ships&lt;/a&gt;, fishing ships, naval ships, submarines (&lt;a href="https://www.usni.org/magazines/naval-history-magazine/2017/october/bluejackets-manual-ships-and-boats-and" rel="noopener noreferrer"&gt;which are boats!&lt;/a&gt;), paddle-boats, etc.  Each ship or boat has a Signalman, whose job is to communicate with other nearby vessels via a formal language of small flags called &lt;em&gt;semaphores&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1pl6zy70aeze3pspbxhs.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1pl6zy70aeze3pspbxhs.jpeg" alt="sempahores" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Image courtesy of &lt;a href="https://twitter.com/owendaveydraws" rel="noopener noreferrer"&gt;@owendaveydraws&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;In particular, the harbor has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A prescribed &lt;em&gt;topology&lt;/em&gt;, in the sense that only certain vessels can communicate with one another.  For example, if your boat is over the horizon from mine, then we cannot communicate, because we cannot see one another.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prescribed &lt;em&gt;interfaces&lt;/em&gt;, in the sense that each vessel has only certain flags it can send or receive.  A vessel cannot stitch together new flags, nor can the Signalman on the vessel magically learn to interpret messages she was not previously trained for.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;em&gt;charter&lt;/em&gt; (📃) denoting the rules that the harbor as a system must abide by.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We use the symbol &lt;code&gt;⊨&lt;/code&gt; to mean &lt;em&gt;models&lt;/em&gt; or &lt;em&gt;makes true&lt;/em&gt; or &lt;em&gt;satisfies&lt;/em&gt;, as in, &lt;code&gt;The-Harbor ⊨ 📃&lt;/code&gt;.  The goal of the attacker is to modify &lt;code&gt;The-Harbor&lt;/code&gt; to some system &lt;code&gt;The-Harbor'&lt;/code&gt;, such that &lt;code&gt;¬ (The-Harbor' ⊨ 📃)&lt;/code&gt;, that is, such that the modified harbor violates the charter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suppose &lt;code&gt;The-Harbor&lt;/code&gt; contains vessels &lt;code&gt;V0, ..., Vn, W0, ..., Wk&lt;/code&gt;, and, &lt;code&gt;The-Harbor ⊨ 📃&lt;/code&gt;.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Replace vessels &lt;code&gt;V0, ..., Vn&lt;/code&gt; with evil doppelgängers &lt;code&gt;V0', ..., Vn'&lt;/code&gt; such that the modified system &lt;code&gt;The-Harbor' = V0' ║ ... ║ Vn' ║ W0 ║ ... ║ Wk&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; model &lt;code&gt;📃&lt;/code&gt;, i.e., &lt;code&gt;¬ (The-Harbor' ⊨ 📃)&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pseudo-Formal Solution
&lt;/h2&gt;

&lt;p&gt;We formalize a gadget called a &lt;em&gt;daisy process&lt;/em&gt;.  Given a Signalman &lt;code&gt;🧔&lt;/code&gt;, the &lt;em&gt;daisy of&lt;/em&gt; &lt;code&gt;🧔&lt;/code&gt; is the simplest non-deterministic automaton that exhausts the space of message-receive and message-send events in the interface of &lt;code&gt;🧔&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, we define &lt;code&gt;The-Harbor'&lt;/code&gt; by replacing &lt;code&gt;V0, ..., Vn&lt;/code&gt; with &lt;code&gt;daisy(V0), ..., daisy(Vn)&lt;/code&gt;, and we model-check the result.  If the model-checker finds no violating runs, then no attackers exist.  On the other hand, if the model-checker finds a violating run, then we automatically translate that violating run into a series of reproducing processes &lt;code&gt;A0, ..., An&lt;/code&gt;.  When we replace &lt;code&gt;V0, ..., Vn&lt;/code&gt; with &lt;code&gt;A0, ..., An&lt;/code&gt;, we get a new system &lt;code&gt;The-Harbor-Attacked&lt;/code&gt; that van violate the charter.  (If &lt;code&gt;W0, ..., Wk&lt;/code&gt; are deterministic, then &lt;code&gt;The-Harbor-Attacked&lt;/code&gt; will &lt;em&gt;always&lt;/em&gt; violate the charter.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Deliverables
&lt;/h2&gt;

&lt;p&gt;Ok, so, we have pseudo-formally described an attack strategy for naval logistics based on program transformations and reduction to model-checking.  But how does this actually manifest in the real world?  How might this impact my Signal chat, or my HBO stream?  &lt;/p&gt;

&lt;p&gt;(It is unlikely to impact your Signal chat; I am not &lt;em&gt;that&lt;/em&gt; good of a cryptographer.)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We built an open-source tool called &lt;a href="https://github.com/maxvonhippel/AttackerSynthesis" rel="noopener noreferrer"&gt;Korg&lt;/a&gt;.  If you are a protocol engineer, or an individual interested in protocol security, we encourage you to download the tool and play with it!  You will need to learn &lt;a href="http://spinroot.com/spin/Man/promela.html" rel="noopener noreferrer"&gt;Promela&lt;/a&gt;, but this is pretty easy.  In fact you can probably learn most of it from just the examples in our &lt;code&gt;demo/&lt;/code&gt; folder.  &lt;a href="https://mxvh.pl/AttackerSynthesis/" rel="noopener noreferrer"&gt;Extensive documentation for our tool is available online.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We wrote a paper about our method, where we applied Korg to the TCP connection establishment and tear-down routine.  We found realistic (known) attacks against TCP totally automatically, in a matter of seconds or minutes.  (TCP is a fundamental protocol of the Internet stack.)  An extended preprint of that paper is available &lt;a href="https://arxiv.org/abs/2004.01220" rel="noopener noreferrer"&gt;on arXiv&lt;/a&gt;; a condensed version will be presented in &lt;a href="http://safecomp2020.di.fc.ul.pt/" rel="noopener noreferrer"&gt;SafeComp 2020&lt;/a&gt; and published in the Springer LNCS series.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;We present the following adorable &lt;a href="https://www.alchemistowl.org/pocorgtfo/" rel="noopener noreferrer"&gt;proof of concept&lt;/a&gt;.  Our models are written in &lt;a href="http://spinroot.com/spin/Man/promela.html" rel="noopener noreferrer"&gt;Promela&lt;/a&gt;, but should be easy enough to read so long as you understand that &lt;code&gt;chan&lt;/code&gt; is a type for channels of communication, &lt;code&gt;mtype&lt;/code&gt; is like an &lt;code&gt;enum&lt;/code&gt;, &lt;code&gt;chan ? msg&lt;/code&gt; means &lt;code&gt;chan.wait-to-recieve(msg)&lt;/code&gt;, and &lt;code&gt;chan ! msg&lt;/code&gt; means &lt;code&gt;chan.send(msg)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, the harbor, without our vulnerable process &lt;code&gt;v0 = Bob&lt;/code&gt;.  The only vessel is an evil pirate named Alice, who is deathly afraid of the royal navy and so will not attack anyone with a royal navy semaphore, but will ruthlessly pillage anyone else until they raise their white flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mtype = { white, royal, pirate, trading }

chan alice2bob = [0] of { mtype }
chan bob2alice = [0] of { mtype }

bool aliceRetired = false

active proctype alice() {
SCOPING:
    if
    :: bob2alice ? _ -&amp;gt; goto PIRATESTUFF;
    fi
PIRATESTUFF:
    alice2bob ! pirate;
    if
    :: bob2alice ? white -&amp;gt; goto SCOPING;
    :: bob2alice ? royal -&amp;gt; goto end;
    fi
end:
    aliceRetired = true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second, the vulnerable process &lt;code&gt;v0 = Bob&lt;/code&gt;, a simple fisherman who has a royal flag but is too dim to use it when confronted with Alice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;active proctype bob() {
FISHING:
    do
    :: bob2alice ! trading;
    :: alice2bob ? pirate -&amp;gt; bob2alice ! white; 
    od
end:
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is Bob's interface in YAML format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bob2alice:
    I:
    O:white,royal,trading
alice2bob:
    I:pirate
    O:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how although Bob isn't programmed to use a royal flag, in theory, he could.&lt;/p&gt;

&lt;p&gt;Let's define a LTL (Linear Temporal Logic) property saying that Alice never gives up or dies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ltl aliceNeverDies {
    always (aliceRetired == false)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can run this problem through Korg.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kWWyREN4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/97RtESe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kWWyREN4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/97RtESe.jpg" alt="Imgur" width="800" height="772"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the result we get is the sensible one, where Bob uses that royal flag and escapes piracy for good.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;active proctype attacker() {

        bob2alice ! royal;
        alice2bob ? pirate;
        bob2alice ! royal;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>formalmethods</category>
      <category>synthesis</category>
      <category>security</category>
      <category>protocol</category>
    </item>
    <item>
      <title>Simple Number-Theoretic Insights with Python</title>
      <dc:creator>Max von Hippel</dc:creator>
      <pubDate>Mon, 22 Jan 2018 21:39:58 +0000</pubDate>
      <link>https://dev.to/maxvonhippel/simple-number-theoretic-insights-with-python-1577</link>
      <guid>https://dev.to/maxvonhippel/simple-number-theoretic-insights-with-python-1577</guid>
      <description>&lt;p&gt;Sometimes I learn about a new operator, or equivalence class, or some other such function from &lt;code&gt;ZxZ&lt;/code&gt; to &lt;code&gt;Z&lt;/code&gt;.  Often looking at a grid of the numbers &lt;code&gt;0 - 9&lt;/code&gt; on &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; axes illuminates interesting properties of such functionals.  Here I will give some code with which to do just that.&lt;/p&gt;

&lt;p&gt;Before I continue, here's a picture of &lt;code&gt;I/O&lt;/code&gt; from the code I will be writing in this blog post / article / thing.  I am including this at the start so that anyone who reads this knows what the goal of the code is to begin with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd770ck1fu551fomgpsij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd770ck1fu551fomgpsij.png" alt="I/O Examples" width="694" height="1132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First let's define a few functionals, or functions, or operations, or whatever.  This way we can quickly see the utility of our &lt;code&gt;number_table&lt;/code&gt; code once we get to that.&lt;/p&gt;

&lt;p&gt;Here are mine, but I encourage you to write your own.  Note that I am coding in &lt;code&gt;Python3&lt;/code&gt;.  The code is simple and I think could be fairly easily ported to your language of choice.&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;# Euclid's Algorithm for Greatest Common Denominator (GCD):
# See https://en.wikipedia.org/wiki/Euclidean_algorithm for more info
&lt;/span&gt;&lt;span class="n"&gt;euclid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;a&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="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;euclid&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Two numbers are called "relatively prime" if their gcd is 1
&lt;/span&gt;&lt;span class="n"&gt;relatively_prime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;a&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="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;euclid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&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="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;modulo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;a&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="n"&gt;and_ab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;a&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, now that we've got a couple cool little functions to investigate out of the way, let's get to the meat of making number grids.  I like to colorize my number-grids by number, so I made a little function for coloring numbers in Python.&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="n"&gt;number_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\033&lt;/span&gt;&lt;span class="s"&gt;[1;3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;;40m &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It doesn't really do anything for numbers greater than 8, but that's ok because if this bothers you then you can find a clever way to fix it.  (This does not bother me.)  Also, if you're interested in numbers bigger than 9 you'll have to modify my code a bit anyway, because I don't currently take that into account in the spacing of my table.&lt;/p&gt;

&lt;p&gt;Now, here's my &lt;code&gt;number_table&lt;/code&gt; code:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;number_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# We assume method is defined
&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;    &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;number_color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&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;     _________________________&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;number_color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&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="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;number_color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &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;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... And here is some more &lt;code&gt;I/O&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb385l4v7g4vam88trr1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb385l4v7g4vam88trr1o.png" alt="Primality" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope this proves useful!&lt;/p&gt;

</description>
      <category>mathematics</category>
      <category>python</category>
      <category>modulo</category>
      <category>cryptology</category>
    </item>
    <item>
      <title>Hi, I'm Max von Hippel</title>
      <dc:creator>Max von Hippel</dc:creator>
      <pubDate>Sat, 10 Jun 2017 06:26:17 +0000</pubDate>
      <link>https://dev.to/maxvonhippel/hi-im-max-von-hippel</link>
      <guid>https://dev.to/maxvonhippel/hi-im-max-von-hippel</guid>
      <description>&lt;p&gt;I have been coding for 8 years.&lt;/p&gt;

&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/maxvonhippel" rel="noopener noreferrer"&gt;maxvonhippel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've worked on a variety of academic and professional projects.  You can check out my open-source resume &lt;a href="http://mxvh.pl/resume/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, or my interactive, open-source landing page &lt;a href="http://mxvh.pl" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I aspire to be a cybersecurity engineer.  If you have a cool open-source security project you're working on and are looking for contributors, shoot me an email!&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
