<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://journal.lunar.sh/feed.xml" rel="self" type="application/atom+xml" /><link href="https://journal.lunar.sh/" rel="alternate" type="text/html" /><updated>2026-03-25T04:52:49+00:00</updated><id>https://journal.lunar.sh/feed.xml</id><title type="html">Lunar Journal</title><subtitle>Welcome to the `Lunar Journal`!&lt;br&gt;&lt;br&gt; `Journal` publications cover various areas in software and electronics engineering.</subtitle><entry><title type="html">A simple GSC loader for COD Black Ops 1</title><link href="https://journal.lunar.sh/2023/gsctool.html" rel="alternate" type="text/html" title="A simple GSC loader for COD Black Ops 1" /><published>2023-09-17T00:00:00+00:00</published><updated>2023-09-17T00:00:00+00:00</updated><id>https://journal.lunar.sh/2023/gsctool</id><content type="html" xml:base="https://journal.lunar.sh/2023/gsctool.html"><![CDATA[<blockquote>
  <p>Learn how <code class="language-plaintext highlighter-rouge">GSC</code> scripts are loaded into <a href="https://en.wikipedia.org/wiki/Call_of_Duty:_Black_Ops">Black Ops 1</a> and how to write your own
simple <code class="language-plaintext highlighter-rouge">GSC</code> loader in <code class="language-plaintext highlighter-rouge">C</code> for the Microsoft Windows version of the game.</p>
</blockquote>

<ol>
  <li><a href="#fond-memories">Fond Memories</a></li>
  <li><a href="#game-script-code">Game Script Code</a></li>
  <li><a href="#gsc-script-call-chain">GSC Script Call Chain</a></li>
  <li><a href="#format-of-raw-gsc-scripts">Format of raw GSC scripts</a></li>
  <li><a href="#loading-and-executing-gsc-script-assets">Loading and executing GSC script assets</a></li>
  <li><a href="#black-ops-offsets">Black Ops Offsets</a></li>
  <li><a href="#source-code">Source Code</a></li>
  <li><a href="#demo">Demo</a></li>
</ol>

<h1 id="fond-memories">Fond Memories</h1>

<p><img src="https://journal.lunar.sh/images/6/01.jpg" alt="Black Ops 1 Zombies" />
Call of Duty: Black Ops 1</p>

<p><code class="language-plaintext highlighter-rouge">Call of Duty: Black Ops 1</code> for Microsoft Windows was released all the back back
in 2010! At the time I was still a teenager in high-school and a dedicated
gamer.</p>

<p>It seemed like another purchase on steam back then but I would have never
expected a game to produce so many fond memories playing kino der toten zombies
with friends from all over the world.</p>

<p>I mean who doesn’t remember all the iconic glitches, mystery boxes, etc of the
game? Some say the <code class="language-plaintext highlighter-rouge">Black Ops 1</code> <code class="language-plaintext highlighter-rouge">zombies</code> was the best in the <code class="language-plaintext highlighter-rouge">Black Ops</code> series.
There is something about the game aesthetics that creates a rush of nostalgia
:video_game:.</p>

<blockquote>
  <p>Ok enough rambling, let’s get technical…</p>
</blockquote>

<h1 id="game-script-code">Game Script Code</h1>

<p><code class="language-plaintext highlighter-rouge">GSC</code> is an internal scripting language that is used to script missions and game
modes for <code class="language-plaintext highlighter-rouge">Black Ops 1</code>. It has a syntax similar to <code class="language-plaintext highlighter-rouge">C++</code> but is a very limited
language. Here is an example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="rouge-code"><pre>#include common_scripts\utility;
#include maps\_utility;

init()
{
	level thread on_player_connect();

	// TODO: put weapon init's here
	maps\_flashgrenades::main();
	maps\_weaponobjects::init();
	maps\_explosive_bolt::init();
	maps\_flamethrower_plight::init();
	maps\_ballistic_knife::init();
}

on_player_connect()
{
	while( true )
	{
		level waittill("connecting", player);

		player.usedWeapons = false;
		player.hits = 0;

		player thread on_player_spawned();
	}
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">GSC</code> scripts are only loaded and executed when a map or game has started and in
<code class="language-plaintext highlighter-rouge">Black Ops 1</code> they are reloaded every time a map or game mode is restarted. Writing
custom <code class="language-plaintext highlighter-rouge">GSC</code> scripts is thus the basis for the vast majority of <code class="language-plaintext highlighter-rouge">Black Ops 1</code>
modding efforts.</p>

<p><code class="language-plaintext highlighter-rouge">GSC</code> scripts are first loaded into memory and then compiled with an internal <code class="language-plaintext highlighter-rouge">GSC</code>
compiler. There is a public <code class="language-plaintext highlighter-rouge">GSC</code> compiler and decompiler on <code class="language-plaintext highlighter-rouge">GitHub</code>:
<a href="https://github.com/xensik/gsc-tool">gsc-tool</a> but support for <code class="language-plaintext highlighter-rouge">Black Ops 1 (T5)</code>
seems to be missing.</p>

<p>Luckily it turns out we don’t actually need an external <code class="language-plaintext highlighter-rouge">GSC</code> compiler to compile
our own <code class="language-plaintext highlighter-rouge">GSC</code> scripts. We can (in theory) simply call the <code class="language-plaintext highlighter-rouge">compile()</code> function of
the internal <code class="language-plaintext highlighter-rouge">GSC</code> compiler and pass our mod script.</p>

<p>Whenever we talk about hooking a function or calling an in-game function we
usually assume that static analysis has been performed on the game binary to
find functions and offsets of interest. <code class="language-plaintext highlighter-rouge">IDA Pro</code> is my disassembler of choice
but <code class="language-plaintext highlighter-rouge">Ghidra</code> is probably also worth mentioning.</p>

<p>For debugging, <code class="language-plaintext highlighter-rouge">Cheat Engine</code> usually does the job quite well. However debugging
<code class="language-plaintext highlighter-rouge">Black Ops 1</code> is not as simple as attaching to the process and setting
breakpoints.</p>

<p>As far as I know this was possible in the official release version of the game,
but the game received multiple updates/patches which introduced various
primitive <code class="language-plaintext highlighter-rouge">anti-debugging</code> and anti cheat detections which must be bypassed.</p>

<p>Usually if I am starting reverse engineering on a game, my first quick option is
<a href="https://github.com/nihilus/ScyllaHide">scyllahide</a>. This seemed to work
for the latest <code class="language-plaintext highlighter-rouge">Black Ops 1</code> patch which allowed me to set breakpoints in game
which aided in the search for various <code class="language-plaintext highlighter-rouge">Black Ops 1</code> function addresses.</p>

<p>As we know research is an important part of any reverse engineering task,
without adequate research you could be wasting hours, days or even months of
your time by doing the same work that others have done before.</p>

<p>So I started research and found out that the source code for the <code class="language-plaintext highlighter-rouge">CoD 4</code> server
was leaked at some point and can be found in the following repo:
<a href="https://github.com/callofduty4x/CoD4x_Server">cod4x_server</a></p>

<p>This is very valuable information and was the basis for understanding how <code class="language-plaintext highlighter-rouge">GSC</code>
scripts are loaded and compiled in game.</p>

<h1 id="gsc-script-call-chain">GSC Script Call Chain</h1>

<p>The next task was figuring out the call chain (sequence of function calls) which
is required for loading custom <code class="language-plaintext highlighter-rouge">GSC</code> scripts. So I decided to search for the
keyword <code class="language-plaintext highlighter-rouge">script</code> and stumbled upon a function called <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code>
<a href="https://github.com/callofduty4x/CoD4x_Server/blob/14f0d8a205d80c9b30e308b57f0cd9bd6d7cdb1c/src/scr_vm_main.c#L1018">here</a>
which seemed to be responsible for loading a <code class="language-plaintext highlighter-rouge">GSC</code> or <code class="language-plaintext highlighter-rouge">CSC</code> script (<code class="language-plaintext highlighter-rouge">CSC</code> scripts are
almost identical to <code class="language-plaintext highlighter-rouge">GSC</code> scripts but are executed by the client instead of a
server).</p>

<p>The only argument to <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code> was a const character string however:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>unsigned int Scr_LoadScript(const char* scriptname)
</pre></td></tr></tbody></table></code></pre></div></div>

<p>which I assumed was some type of resource/asset string. I therefore proceeded to
look for any functions that would load assets and stumbled upon <code class="language-plaintext highlighter-rouge">DB_AddXAsset</code>
<a href="https://github.com/callofduty4x/CoD4x_Server/blob/14f0d8a205d80c9b30e308b57f0cd9bd6d7cdb1c/src/bspc/db_miniload.cpp#L2919">here</a>.</p>

<p>The function signature for <code class="language-plaintext highlighter-rouge">DB_addXAasset</code> was as follows:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>XAssetHeader __cdecl DB_AddXAsset(XAssetType type, XAssetHeader header)
</pre></td></tr></tbody></table></code></pre></div></div>

<p>I decided to search for the definition of <code class="language-plaintext highlighter-rouge">XAssetHeader</code>. <code class="language-plaintext highlighter-rouge">XAssetHeader</code> was
defined as a union of various
<a href="https://github.com/callofduty4x/CoD4x_Server/blob/14f0d8a205d80c9b30e308b57f0cd9bd6d7cdb1c/src/xassets.h#L81">structs</a>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre>union XAssetHeader
{
  struct XModelPieces *xmodelPieces;
  struct PhysPreset *physPreset;
  struct XAnimParts *parts;
  ...
  struct FxImpactTable *impactFx;
  struct RawFile *rawfile;
  struct StringTable *stringTable;
  void *data;
};
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Out of all the structs listed <code class="language-plaintext highlighter-rouge">RawFile</code> seemed like the most interesting for our
purposes (loading <code class="language-plaintext highlighter-rouge">GSC</code> script assets). Let’s have a look at the <code class="language-plaintext highlighter-rouge">Rawfile</code>
structure
<a href="https://github.com/callofduty4x/CoD4x_Server/blob/14f0d8a205d80c9b30e308b57f0cd9bd6d7cdb1c/src/xassets/rawfile.h#L5">itself</a>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>struct RawFile
{
  const char *name;
  int len;
  const char *buffer;
};
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Seems simple enough:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">name</code> is the resource/asset identifier.</li>
  <li><code class="language-plaintext highlighter-rouge">len</code> is the total buffer length.</li>
  <li><code class="language-plaintext highlighter-rouge">buffer</code> is the buffer holding our script to compile.</li>
</ul>

<p>One thing worth noting is that we don’t actually know the format that scripts
are stored in before they are compiled (i.e format of <code class="language-plaintext highlighter-rouge">buffer</code>). For example,
are they plaintext, compressed or encrypted at all? We will discuss this further
on.</p>

<p>Let us now for a brief moment turn our attention to the following code block:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>XAssetEntry newEntry;

newEntry.asset.type = type;
newEntry.asset.header = header;

existingEntry = DB_LinkXAssetEntry(&amp;newEntry, 0);
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This seems to be doing the actual asset allocation. The first argument is of type
<code class="language-plaintext highlighter-rouge">XAssetEntry</code> which is defined as:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre>struct XAssetEntry
{
  struct XAsset asset;
  byte zoneIndex;
  bool inuse;
  uint16_t nextHash;
  uint16_t nextOverride;
  uint16_t usageFrame;
};
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The first element of this struct <code class="language-plaintext highlighter-rouge">asset</code> looks interesting:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>struct XAsset
{
  enum XAssetType type;
  union XAssetHeader header;
};
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We know what <code class="language-plaintext highlighter-rouge">XAssetHeader</code> is and <code class="language-plaintext highlighter-rouge">XAssetType</code> is a simple enum which is used
to indicate the asset type:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>enum XAssetType
{
  ASSET_TYPE_XMODELPIECES,
  ASSET_TYPE_PHYSPRESET,
  ASSET_TYPE_XANIMPARTS,
  ...
  ASSET_TYPE_RAWFILE
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">ASSET_TYPE_RAWFILE</code> seems like the right enum value in our case. With all this
information we now know what is required to load a script asset:</p>

<ol>
  <li>Allocate <code class="language-plaintext highlighter-rouge">RawFile</code> struct with script name, size and data buffer.</li>
  <li>Initialise <code class="language-plaintext highlighter-rouge">XAssetHeader</code> union with pointer to our <code class="language-plaintext highlighter-rouge">Rawfile</code> struct.</li>
  <li>Allocate <code class="language-plaintext highlighter-rouge">XAssetEntry</code> struct.</li>
  <li>Set <code class="language-plaintext highlighter-rouge">asset.type</code> to <code class="language-plaintext highlighter-rouge">ASSET_TYPE_RAWFILE</code> (<code class="language-plaintext highlighter-rouge">XAssetEntry</code>).</li>
  <li>Set <code class="language-plaintext highlighter-rouge">asset.header</code> to <code class="language-plaintext highlighter-rouge">XAssetHeader</code> allocated earlier (<code class="language-plaintext highlighter-rouge">XAssetEntry</code>).</li>
  <li>Call <code class="language-plaintext highlighter-rouge">DB_LinkXAssetEntry</code> to ‘link’ the asset.</li>
</ol>

<p>After this series of steps it should be possible to call <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code> with
the path of our asset. This would be the same as the <code class="language-plaintext highlighter-rouge">name</code> member of the
<code class="language-plaintext highlighter-rouge">RawFile</code> struct.</p>

<h1 id="format-of-raw-gsc-scripts">Format of raw GSC scripts</h1>

<p>We now have most of the required information to load <code class="language-plaintext highlighter-rouge">GSC</code> script assets into
memory but one question remains, what format are they in?</p>

<p>To answer this question I thought a good starting point would be to hook/detour
<code class="language-plaintext highlighter-rouge">DB_LinkXAssetEntry</code> and dump the <code class="language-plaintext highlighter-rouge">RawFile</code> data buffer for a <code class="language-plaintext highlighter-rouge">GSC</code> script to a
file for analysis.</p>

<p>To detour functions in the game we need to bypass an annoying <code class="language-plaintext highlighter-rouge">anti-debug</code>
feature introduced into the game that uses <code class="language-plaintext highlighter-rouge">GetTickCount</code> to analyse a thread’s
timing behaviour.</p>

<p>Using Cheat Engine I managed to trace the evil function to <code class="language-plaintext highlighter-rouge">0x004C06E0</code>:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="cp">#define T5_Thread_Timer 0x004C06E0
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p><img src="https://journal.lunar.sh/images/6/03.jpg" alt="Anti Debug Timer" />
Anti-debug timer view in <code class="language-plaintext highlighter-rouge">IDA</code>.</p>

<p>So make sure you patch this out otherwise the game will simply close after some
time after detouring.</p>

<p>We would have to hook the function before loading a solo zombie match as script
assets are loaded into memory shortly after starting a game mode. I wrote a
simple detouring library called <a href="https://github.com/lunar-sh/cdl86">cdl86</a>
that can <code class="language-plaintext highlighter-rouge">hook/detour</code> functions either by inserting a <code class="language-plaintext highlighter-rouge">JMP</code> opcode at the target
functions address to a detour function or through a software breakpoint.</p>

<p>I will leave this task up to the reader to perform. What you need is an address
and I took the liberty of finding the address of <code class="language-plaintext highlighter-rouge">DB_LinkXAssetEntry</code> for you in
<code class="language-plaintext highlighter-rouge">IDA Pro</code>. If you are wondering how I found the address, it would be a combination
of research, debugging and static analysis.</p>

<p>A lot comes down to recognising patterns in the disassembly. In general as you
find the address of functions it gradually becomes easier to find the address of
other related functions.</p>

<p>Bare in mind this is the address of the last <code class="language-plaintext highlighter-rouge">x86</code> (<code class="language-plaintext highlighter-rouge">32-bit</code>) <code class="language-plaintext highlighter-rouge">PC</code> version of the
game:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="cp">#define T5_DB_LinkXAssetEntry 0x007A2F10
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>Once you have a <code class="language-plaintext highlighter-rouge">GSC</code> script dump, open it in your favorite text editor (I used
<code class="language-plaintext highlighter-rouge">HxD</code>). This is a dump of a small <code class="language-plaintext highlighter-rouge">GSC</code> script from memory:</p>

<p><img src="https://journal.lunar.sh/images/6/02.jpg" alt="GSC Dump" /></p>

<p>We can immediately see that the script is not stored in simple plaintext. In
this case I like to look for <code class="language-plaintext highlighter-rouge">magic</code> bytes which may indicate if the file was
compressed. <code class="language-plaintext highlighter-rouge">zlib</code> compression is one of the most common compression types for
binary files.</p>

<p>Based off research I did, <code class="language-plaintext highlighter-rouge">zlib</code> uses the following magic bytes:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>78 01 - No Compression/low
78 9C - Default Compression
78 DA - Best Compression
</pre></td></tr></tbody></table></code></pre></div></div>

<p>These bytes should appear not too far from the start of the file. Notice that in
the dump these bytes appear at offset <code class="language-plaintext highlighter-rouge">0x8</code> and <code class="language-plaintext highlighter-rouge">0x9</code> so there is a good chance
this file is <code class="language-plaintext highlighter-rouge">zlib</code> compressed. Let’s test this theory, here is a simple <code class="language-plaintext highlighter-rouge">zlib</code>
<code class="language-plaintext highlighter-rouge">inflate</code> python script:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>import zlib

with open(sys.argv[1], 'rb') as compressed_data:
    compressed_data = compressed_data.read()
    unzipped = zlib.decompress(compressed_data[8:])
    with open(sys.argv[2], 'wb') as result:
        result.write(unzipped);
        result.close()
</pre></td></tr></tbody></table></code></pre></div></div>

<p>I get the following text:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="rouge-code"><pre>// THIS FILE IS AUTOGENERATED, DO NOT MODIFY
main()
{
	self setModel("c_jap_takeo_body");
	self.voice = "vietnamese";
	self.skeleton = "base";
}

precache()
{
	precacheModel("c_jap_takeo_body");
}

</pre></td></tr></tbody></table></code></pre></div></div>
<p>This text has a size of <code class="language-plaintext highlighter-rouge">0xC6</code>.</p>

<p>Great and <code class="language-plaintext highlighter-rouge">+1</code> for the data being stored in plaintext!</p>

<p>So what are the first <code class="language-plaintext highlighter-rouge">8</code> bytes used for?</p>

<p>If you have a sharp eye you might have noticed that this 8 bytes actually
contains <code class="language-plaintext highlighter-rouge">2</code> values.</p>

<p>The first <code class="language-plaintext highlighter-rouge">4</code> bytes seems to represent our <code class="language-plaintext highlighter-rouge">inflated</code> (decompressed) data size of
<code class="language-plaintext highlighter-rouge">0xC6</code> and the second value seems to represent the <code class="language-plaintext highlighter-rouge">size of the file - 8 bytes</code>
or the size of our compressed data which is <code class="language-plaintext highlighter-rouge">0x9A</code>.</p>

<p>These values seem to be stored in <code class="language-plaintext highlighter-rouge">little-endian</code> format with the <code class="language-plaintext highlighter-rouge">4</code> byte integers
ordered as <code class="language-plaintext highlighter-rouge">LSB</code>.</p>

<p>Great we now have enough information to load a plaintext <code class="language-plaintext highlighter-rouge">GSC</code> script, compress it
and load it as an asset using <code class="language-plaintext highlighter-rouge">DB_LinkXAssetEntry</code>. It’s pretty cool that it is
this straightforward to decompress <code class="language-plaintext highlighter-rouge">GSC</code> scripts as it gives insight into how the
game modes/logic were implemented and plenty of ideas for mods of course!</p>

<p>So in theory we could inject a <code class="language-plaintext highlighter-rouge">DLL</code>, read our <code class="language-plaintext highlighter-rouge">GSC</code> script, compress it, link it
with <code class="language-plaintext highlighter-rouge">DB_LinkXAssetEntry</code> and then call <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code> right? We will discuss
this in the next section.</p>

<h1 id="loading-and-executing-gsc-script-assets">Loading and executing GSC script assets</h1>

<p>It turns out that we cannot simply call <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code> when we like. As
mentioned above <code class="language-plaintext highlighter-rouge">CoD</code> <code class="language-plaintext highlighter-rouge">Black Ops</code> will load all script assets using
<code class="language-plaintext highlighter-rouge">DB_LinkXAssetEntry</code> and then compile them using <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code> while a map is
loading.</p>

<p>Therefore we have to load our <code class="language-plaintext highlighter-rouge">GSC</code> script at the correct time otherwise it won’t
work. The strategy is therefore to hook <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code> and then load our
custom <code class="language-plaintext highlighter-rouge">GSC</code> script asset when <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code> is loading one of the last <code class="language-plaintext highlighter-rouge">GSC</code>
scripts for the current map.</p>

<p>It turns out that one of the last <code class="language-plaintext highlighter-rouge">GSC</code> scripts contains the current map name.</p>

<p>To get the value of the current map we can utilize the function <code class="language-plaintext highlighter-rouge">Dvar_FindVar</code>
which i found to be at address: <code class="language-plaintext highlighter-rouge">0x0057FF80</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>#define T5_Dvar_FindVar 0x0057FF80
</pre></td></tr></tbody></table></code></pre></div></div>

<p>It’s function prototype is defined as follows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>typedef uint8_t* (__cdecl* Dvar_FindVar_t)(
	uint8_t* variable
);
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The variable in question is <code class="language-plaintext highlighter-rouge">mapname</code> which will return the current map. It
should be noted that <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code> does not execute our <code class="language-plaintext highlighter-rouge">GSC</code> script however,
instead we defer execution of our main function in our <code class="language-plaintext highlighter-rouge">GSC</code> script until the map
has finished loading.</p>

<p>To this end i found a convenient function that is called when the game is just
about to start at address <code class="language-plaintext highlighter-rouge">0x004B7F80</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>#define T5_Scr_LoadGameType 0x004B7F80
</pre></td></tr></tbody></table></code></pre></div></div>

<p>with the following signature:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>typedef void (__cdecl* Scr_LoadGameType_t)(
	void
);
</pre></td></tr></tbody></table></code></pre></div></div>

<p>To defer execution however we need to obtain the function handle after the <code class="language-plaintext highlighter-rouge">GSC</code>
script has been loaded in our hooked <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code>. In this case we utilize a
function called <code class="language-plaintext highlighter-rouge">Scr_GetFunctionHandle</code> which returns the address of a function
which has been loaded into the <code class="language-plaintext highlighter-rouge">GSC</code> execution environment or <code class="language-plaintext highlighter-rouge">VM</code>.</p>

<p>It has the following function signature:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>typedef int32_t (__cdecl* Scr_GetFunctionHandle_t)(
	int32_t scriptInstance,
	const uint8_t* scriptName,
	const uint8_t* functioName
);
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">scriptInstance</code> is a variable which determines whether the script is a <code class="language-plaintext highlighter-rouge">GSC</code> or
<code class="language-plaintext highlighter-rouge">CSC</code> type script. A value of <code class="language-plaintext highlighter-rouge">0</code> indicates a <code class="language-plaintext highlighter-rouge">GSC</code> script while <code class="language-plaintext highlighter-rouge">1</code> indicated a <code class="language-plaintext highlighter-rouge">CSC</code>
script.</p>

<p>The function handle to our loaded script is then stored in a global variable and
the function can be executed in it’s own thread using <code class="language-plaintext highlighter-rouge">Scr_ExecThread</code> which has
the following prototype:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>typedef uint16_t (__cdecl* Scr_ExecThread_t)(
	int32_t scriptInstance,
	int32_t handle,
	int32_t paramCount
);
</pre></td></tr></tbody></table></code></pre></div></div>

<p>I found this function at address: <code class="language-plaintext highlighter-rouge">0x005598E0</code>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>#define T5_Scr_ExecThread 0x005598E0
</pre></td></tr></tbody></table></code></pre></div></div>

<p>I also noticed during static analysis that a call to <code class="language-plaintext highlighter-rouge">T5_Scr_FreeThread</code> was
always made following a call to <code class="language-plaintext highlighter-rouge">Scr_ExecThread</code> so that the pseudo code would
look something like:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>int16_t handle = Scr_ExecThread(0, func_handle, 0);
Scr_FreeThread(handle, 0);
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We also obviously also need a compression library and for this I am using
<a href="https://github.com/lunar-sh/miniz">miniz</a>.</p>

<p>So to summarize the steps to inject our <code class="language-plaintext highlighter-rouge">GSC</code> script via our <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code> hook:</p>

<ol>
  <li>Query map being loaded with <code class="language-plaintext highlighter-rouge">Dvar_FindVar</code>.</li>
  <li>Compare current <code class="language-plaintext highlighter-rouge">scriptName</code> with map name.</li>
  <li>On match open <code class="language-plaintext highlighter-rouge">GSC</code> script, compress and load asset as described above.</li>
  <li>Call <code class="language-plaintext highlighter-rouge">Scr_LoadScript</code> on our loaded script asset.</li>
  <li>Get function handle with <code class="language-plaintext highlighter-rouge">Scr_GetFunctionHandle</code>.</li>
</ol>

<p>To execute our <code class="language-plaintext highlighter-rouge">GSC</code> script entry function via our <code class="language-plaintext highlighter-rouge">Scr_LoadGameType_hk</code> hook:</p>
<ol>
  <li>Call <code class="language-plaintext highlighter-rouge">Scr_ExecThread</code> on function handle.</li>
  <li>Call <code class="language-plaintext highlighter-rouge">Scr_FreeThread</code> on handle returned by <code class="language-plaintext highlighter-rouge">Scr_ExecThread</code>.</li>
</ol>

<h1 id="black-ops-offsets">Black Ops Offsets</h1>

<p>I have included all the offsets I found for the game using <code class="language-plaintext highlighter-rouge">IDA</code>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre>#define T5_Scr_LoadScript         0x00661AF0
#define T5_Scr_GetFunctionHandle  0x004E3470
#define T5_DB_LinkXAssetEntry     0x007A2F10
#define T5_Scr_ExecThread         0x005598E0
#define T5_Scr_FreeThread         0x005DE2C0
#define T5_Scr_LoadGameType       0x004B7F80
#define T5_Dvar_FindVar           0x0057FF80
#define T5_Assign_Hotfix          0x007A4800
#define T5_init_trigger           0x00C793B0
#define T5_Thread_Timer           0x004C06E0
</pre></td></tr></tbody></table></code></pre></div></div>

<p>A simple challenge would be to find these offsets yourself, it is not difficult.</p>

<p><code class="language-plaintext highlighter-rouge">Black Ops 1</code> uses the <code class="language-plaintext highlighter-rouge">__cdecl</code> calling convention for functions.</p>

<h1 id="source-code">Source Code</h1>

<p>I have included the source code of my simple <code class="language-plaintext highlighter-rouge">GSC</code> loader in the
<a href="https://github.com/lunar-sh/gsctool/">following</a> repo.</p>

<p>I have also included a sample <code class="language-plaintext highlighter-rouge">GSC</code> script that spawns a raygun at spawn in
zombies solo mode and dumps <code class="language-plaintext highlighter-rouge">GSC</code> scripts as they are loaded via a
<code class="language-plaintext highlighter-rouge">DB_LinkXAssetEntry</code> hook.</p>

<h1 id="demo">Demo</h1>

<p><img src="https://journal.lunar.sh/images/6/gscdemo.png" alt="" /></p>

<h1 id="signature">Signature</h1>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="rouge-code"><pre>+---------------------------------------+
|     .-.       .-.       .-.           |
|    /   \     /   \     /   \     +    |
|         \   /     \   /     \   /     |
|          "_"       "_"       "_"      |
|                                       |
|  _   _   _ _  _   _   ___   ___ _  _  |
| | | | | | | \| | /_\ | _ \ / __| || | |
| | |_| |_| | .` |/ _ \|   /_\__ \ __ | |
| |____\___/|_|\_/_/ \_\_|_(_)___/_||_| |
|                                       |
|                                       |
| Lunar RF Labs                         |
| Email: root@lunar.sh                  |
|                                       |
| Research Laboratories                 |
| OpenAlias (BTC, XMR): lunar.sh        |
| Copyright (C) 2022-2024               |
+---------------------------------------+
</pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name>Dylan Müller</name></author><summary type="html"><![CDATA[Learn how GSC scripts are loaded into Black Ops 1 and how to write your own simple GSC loader in C for the Microsoft Windows version of the game.]]></summary></entry><entry><title type="html">A Tiny C (x86_64) Function Hooking Library</title><link href="https://journal.lunar.sh/2022/linux-detours.html" rel="alternate" type="text/html" title="A Tiny C (x86_64) Function Hooking Library" /><published>2022-12-31T00:00:00+00:00</published><updated>2022-12-31T00:00:00+00:00</updated><id>https://journal.lunar.sh/2022/linux-detours</id><content type="html" xml:base="https://journal.lunar.sh/2022/linux-detours.html"><![CDATA[<blockquote>
  <p>Function detouring is a powerful hooking technique that allows for the
interception of <code class="language-plaintext highlighter-rouge">C/C++</code> functions. <code class="language-plaintext highlighter-rouge">cdl86</code> aims to be a tiny <code class="language-plaintext highlighter-rouge">C</code> detours
library for <code class="language-plaintext highlighter-rouge">x86_64</code> binaries.</p>
</blockquote>

<ol>
  <li><a href="#overview">Overview</a></li>
  <li><a href="#jmp-patching">JMP Patching</a></li>
  <li><a href="#int3-patching">INT3 Patching</a></li>
  <li><a href="#code-injection">Code Injection</a></li>
  <li><a href="#api">API</a></li>
  <li><a href="#source-code">Source Code</a></li>
</ol>

<h1 id="overview">Overview</h1>

<p>Note: This article details the linux specific details of the library. Windows
support has since been added.</p>

<p>See:
<a href="https://github.com/lunar-sh/cdl86">https://github.com/lunar-sh/cdl86</a></p>

<p><a href="https://en.wikipedia.org/wiki/Microsoft_Research">Microsoft Research</a> currently
maintains a library known as <a href="https://github.com/microsoft/Detours">MS Detours</a>.
It allows for the interception of Windows <code class="language-plaintext highlighter-rouge">API</code> calls within the memory address
space of a process.</p>

<p>This might be useful in certain situations such as if you are writing a <code class="language-plaintext highlighter-rouge">D3D9</code>
(<code class="language-plaintext highlighter-rouge">DirectX</code>) hook and you need to intercept cetain graphics routines. This is
commonly done for <code class="language-plaintext highlighter-rouge">ESP</code> and wallhacks where the <code class="language-plaintext highlighter-rouge">Z-buffer</code> needs to be
disabled for certain character models, for <code class="language-plaintext highlighter-rouge">D3D9</code> this might involve hooking
<code class="language-plaintext highlighter-rouge">DrawIndexedPrimitive</code>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre>HRESULT WINAPI hkDrawIndexedPrimitive(LPDIRECT3DDEVICE9 pDevice, ...args)
{
    // Check play model strides, primitive count, etc
    ...
    pDevice-&gt;SetRenderState(D3DRS_ZENABLE, false);
    ...
    // Call original function and return
    oDrawIndexedPrimitive(...)
    return ...
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>In order to disable the <code class="language-plaintext highlighter-rouge">Z-buffer</code> in this example we need access to a valid
<code class="language-plaintext highlighter-rouge">LPDIRECT3DDEVICE9</code> context within the running process. This is where detours
comes in handy. Generally, the procedure to hook a specific function is as
follows:</p>

<ul>
  <li>Declare a function pointer with target function signature:</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>typedef HRESULT (WINAPI* tDrawIndexedPrimitive)(LPDIRECT3DDEVICE9 pDevice, ...args);
</pre></td></tr></tbody></table></code></pre></div></div>

<ul>
  <li>Define detour function with same function signature:</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>HRESULT WINAPI hkDrawIndexedPrimitive(LPDIRECT3DDEVICE9 pDevice, ...args)
</pre></td></tr></tbody></table></code></pre></div></div>

<ul>
  <li>Assign the function pointer the target functions address in memory. In this
case a <code class="language-plaintext highlighter-rouge">VTable</code> entry.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>#define DIP 0x55
tDrawIndexedPrimitive oDrawIndexedPrimitive = (oDrawIndexedPrimitive)SomeVTable[DIP];
</pre></td></tr></tbody></table></code></pre></div></div>

<ul>
  <li>Call DetourFunction:</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>DetourFunction((void**)&amp;oDrawIndexedPrimitive, &amp;hkhkDrawIndexedPrimitive)
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">DetourFunction</code> then uses the <code class="language-plaintext highlighter-rouge">oDrawIndexedPrimitive</code> function pointer and
modifies the instructions at the target function in order to transfer control
flow to the detour function.</p>

<p>At this point any calls to <code class="language-plaintext highlighter-rouge">DrawIndexedPrimitive</code> within the <code class="language-plaintext highlighter-rouge">LPDIRECT3DDEVICE9</code>
class will be rerouted to <code class="language-plaintext highlighter-rouge">hkDrawIndexedPrimitive</code>. You can see that this is a
very powerful concept and gives us access to the callee’s function arguments. As
demonstrated, it is possible to hook both <code class="language-plaintext highlighter-rouge">C</code> and <code class="language-plaintext highlighter-rouge">C++</code> functions.</p>

<p>The difference generally is that the first argument to a <code class="language-plaintext highlighter-rouge">C++</code> function is a
hidden <code class="language-plaintext highlighter-rouge">this</code> pointer. Therefore you can define a <code class="language-plaintext highlighter-rouge">C++</code> detour in <code class="language-plaintext highlighter-rouge">C</code> with this
extra argument.</p>

<p>Detours is great, but it is only available for Windows. The aim of the <code class="language-plaintext highlighter-rouge">cdl86</code>
project is to create a simple, compact detours library for <code class="language-plaintext highlighter-rouge">x86_64</code> Linux. What
follows is a brief explanation on how the library was designed.</p>

<h1 id="detour-methods">Detour methods</h1>

<p>Two different approaches to method detouring were investigated and implemented
in the <code class="language-plaintext highlighter-rouge">cdl86</code> <code class="language-plaintext highlighter-rouge">C</code> library. First let’s have a look at a typical function call for a
simple <code class="language-plaintext highlighter-rouge">C</code> program. We will be using <code class="language-plaintext highlighter-rouge">GDB</code> to inspect the resulting disassembly.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre>#include &lt;stdio.h&gt;

int add(int x, int y)
{
    return x + y;
}
int main()
{
    printf("%i", add(1,1));
    return 0;
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Compile with:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>gcc main.c -o main
</pre></td></tr></tbody></table></code></pre></div></div>

<p>and then debug with <code class="language-plaintext highlighter-rouge">GDB</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>gdb main
</pre></td></tr></tbody></table></code></pre></div></div>

<p>To list all the functions in the binary, supply <code class="language-plaintext highlighter-rouge">info functions</code> to the <code class="language-plaintext highlighter-rouge">gdb</code>
command prompt.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre>0x0000000000001100  __do_global_dtors_aux
0x0000000000001140  frame_dummy
0x0000000000001149  add
0x0000000000001161  main
0x00000000000011a0  __libc_csu_init
0x0000000000001210  __libc_csu_fini
0x0000000000001218  _fini
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Let’s disassemble the main function with <code class="language-plaintext highlighter-rouge">disas /r main</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>Dump of assembler code for function main:
   0x0000000000001161 &lt;+0&gt;:     f3 0f 1e fa     endbr64
   0x0000000000001165 &lt;+4&gt;:     55      push   %rbp
   0x0000000000001166 &lt;+5&gt;:     48 89 e5        mov    %rsp,%rbp
   0x0000000000001169 &lt;+8&gt;:     be 01 00 00 00  mov    $0x1,%esi
   0x000000000000116e &lt;+13&gt;:    bf 01 00 00 00  mov    $0x1,%edi
   0x0000000000001173 &lt;+18&gt;:    e8 d1 ff ff ff  callq  0x1149 &lt;add&gt;
   0x0000000000001178 &lt;+23&gt;:    89 c6   mov    %eax,%esi
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">callq</code> has one operand which is the address of the function being called. It
pushes the current value of <code class="language-plaintext highlighter-rouge">%rip</code> (next instruction after call) onto the stack
and then transfers control flow to the target function.</p>

<p>You may have also noticed the presence of the <code class="language-plaintext highlighter-rouge">endbr64</code> instruction. This
instruction is specific to Intel processors and is part of <a href="https://software.intel.com/content/www/us/en/develop/articles/technical-look-control-flow-enforcement-technology.html">Intel’s Control-Flow
Enforcement Technology
(CET)</a>.
<code class="language-plaintext highlighter-rouge">CET</code> is designed to provide hardware protection against <code class="language-plaintext highlighter-rouge">ROP</code> (Return-orientated
Programming) and similar methods which manipulate control flow using <em>existing</em>
byte code.</p>

<p>It’s two main features are:</p>

<ul>
  <li>A shadow stack for tracking return addresses.</li>
  <li>Indirect branch tracking, which <code class="language-plaintext highlighter-rouge">endbr64</code> is a part of.</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">Intel CET</code> however does not prevent us from modifying control flow <strong>directly</strong>
by inserting instructions into memory.</p>

<h1 id="jmp-patching">JMP Patching</h1>

<p>The first method of function detouring we will explore is by inserting a <code class="language-plaintext highlighter-rouge">JMP</code>
instruction at the beginning of the target function to transfer control over to
the detour function. It should be noted that in order to preserve the stack we
need to use a <code class="language-plaintext highlighter-rouge">JMP</code> (specifically <code class="language-plaintext highlighter-rouge">jmpq</code>) instruction rather than a <code class="language-plaintext highlighter-rouge">CALL</code>.</p>

<p>Since there is no way to pass a <code class="language-plaintext highlighter-rouge">64-bit</code> address to the <code class="language-plaintext highlighter-rouge">jmpq</code> instruction we will
have to first store the address we want to jump to into a register. We need to
choose a register that is not part of the <code class="language-plaintext highlighter-rouge">__cdecl</code> (defualt) calling
convention. <code class="language-plaintext highlighter-rouge">%rax</code> happens to be a register that is not part of the <code class="language-plaintext highlighter-rouge">__cdecl</code>
userspace calling convention and so for simplicity we use this register in our
design.</p>

<p>The following is a disassembly of the instructions required for a <code class="language-plaintext highlighter-rouge">JMP</code> to a
<code class="language-plaintext highlighter-rouge">64-bit</code> immediate address:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>0x0000555555561389 &lt;+0&gt;: 48 b8 b1 13 56 55 55 55 00 00 movabs $0x5555555613b1,%rax
0x0000555555561393 &lt;+10&gt;: ff e0	jmpq   *%rax
</pre></td></tr></tbody></table></code></pre></div></div>

<p>You can see that <code class="language-plaintext highlighter-rouge">12</code> bytes are required to encode the <code class="language-plaintext highlighter-rouge">movabs</code> instruction (which
moves the detour address into <code class="language-plaintext highlighter-rouge">%rax</code>) as well as the <code class="language-plaintext highlighter-rouge">jmpq</code> instruction.
Immediate values are stored in little endian (LE) encoding.</p>

<p>So we can therefore conclude that we need to patch <strong>at least</strong> <code class="language-plaintext highlighter-rouge">12</code> bytes in
memory at the location of our target function. These <code class="language-plaintext highlighter-rouge">12</code> bytes however are
important and we cannot simply discard them. It turns out that we actually place
these bytes at the start of what I will call a ‘trampoline function’, it’s
layout is as follows:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>trampoline &lt;0x23215412&gt;:
    (original instruction bytes which were patched)
    JMP (target + JMP patch length)
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Simply put, the trampoline function behaves as the original, unpatched function.
As shown above it consists of the target function’s original instruction bytes
as well as a call to the target function, offset by the <code class="language-plaintext highlighter-rouge">JMP</code> patch length.</p>

<p>The trampoline generation code for <code class="language-plaintext highlighter-rouge">cdl86</code> is shown below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="rouge-code"><pre>uint8_t *cdl_gen_trampoline(uint8_t *target, uint8_t *bytes_orig, int size)
{
    uint8_t *trampoline;
    int prot = 0x0;
    int flags = 0x0;

    /* New function should have read, write and
     * execute permissions.
     */
    prot = PROT_READ | PROT_WRITE | PROT_EXEC;
    flags = MAP_PRIVATE | MAP_ANONYMOUS;

    /* We use mmap to allocate trampoline memory pool. */
    trampoline = mmap(NULL, size + BYTES_JMP_PATCH, prot, flags, -1, 0);
    memcpy(trampoline, bytes_orig, size);
    /* Generate jump to address just after call
     * to detour in trampoline. */
    cdl_gen_jmpq_rax(trampoline + size, target + size);

    return trampoline;
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>You can see that the allocation of the trampoline function occurs through a call
to <code class="language-plaintext highlighter-rouge">mmap</code> with the <code class="language-plaintext highlighter-rouge">PROT_READ | PROT_WRITE | PROT_EXEC</code> memory protection flags.</p>

<p>Therefore it should also be noted that the correct memory permissions should be
set for both the target function before modification as well as the trampoline
function, after allocation. Here is a snippet from the <code class="language-plaintext highlighter-rouge">cdl86</code> library for
setting memory attributes:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre>/* Set R/W memory protections for code page. */
int cdl_set_page_protect(uint8_t *code)
{
    int perms = 0x0;
    int ret = 0x0;

    /* Read, write and execute perms. */
    perms = PROT_EXEC | PROT_READ | PROT_WRITE;
    /* Calculate page size */
    uintptr_t page_size = sysconf(_SC_PAGE_SIZE);
    ret = mprotect(code - ((uintptr_t)(code) % page_size), page_size, perms);

    return ret;
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The general procedure to place the <code class="language-plaintext highlighter-rouge">JMP</code> hook is as follows:</p>

<ol>
  <li>Determine the minimum number of bytes required for a <code class="language-plaintext highlighter-rouge">JMP</code> patch.</li>
  <li>Create trampoline function.</li>
  <li>Set memory permissions (read, write, execute).</li>
  <li>Generate <code class="language-plaintext highlighter-rouge">JMP</code> to detour at target function.</li>
  <li>Fill unused bytes with <code class="language-plaintext highlighter-rouge">NOP</code>.</li>
  <li>Assign trampoline address to target function pointer.</li>
</ol>

<p>Let’s have a look at all of this in action using <code class="language-plaintext highlighter-rouge">GDB</code>. I will be using the
<a href="https://github.com/lunar-sh/cdl86/blob/master/tests/basic_jmp.c">basic_jmp.c</a>
test case in the <code class="language-plaintext highlighter-rouge">cdl86</code> library. The source code for this test case is shown
below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
</pre></td><td class="rouge-code"><pre>#include "cdl.h"

typedef int add_t(int x, int y);
add_t *addo = NULL;

int add(int x, int y)
{
    printf("Inside original function\n");
    return x + y;
}

int add_detour(int x, int y)
{
    printf("Inside detour function\n");
    return addo(5,5);
}

int main()
{
    struct cdl_jmp_patch jmp_patch = {};
    addo = (add_t*)add;

    printf("Before attach: \n");
    printf("add(1,1) = %i\n\n", add(1,1));

    jmp_patch = cdl_jmp_attach((void**)&amp;addo, add_detour);
    if(jmp_patch.active)
    {
        printf("After attach: \n");
        printf("add(1,1) = %i\n\n", add(1,1));
        printf("== DEBUG INFO ==\n");
        cdl_jmp_dbg(&amp;jmp_patch);
    }

    cdl_jmp_detach(&amp;jmp_patch);
    printf("\nAfter detach: \n");
    printf("add(1,1) = %i\n\n", add(1,1));

    return 0;
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We compile the following source file with (modified from makefile):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>gcc -I../ -g basic_jmp.c ../cdl.c ../lib/libudis86/*.c -g -o basic_jmp
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Then load into <code class="language-plaintext highlighter-rouge">GDB</code> using:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>gdb basic_jmp
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Once <code class="language-plaintext highlighter-rouge">GDB</code> has loaded, we insert a breakpoints at lines <code class="language-plaintext highlighter-rouge">24</code> and <code class="language-plaintext highlighter-rouge">27</code> using the
command:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>break 24
break 27
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We start execution of the program with:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>run
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">GDB</code> will then inform you that the first breakpoint has been triggered. For this
first breakpoint we are interested in the <code class="language-plaintext highlighter-rouge">add()</code> function’s assembly before the
hook has taken place. To inspect this assembly, provide:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>disas /r add
</pre></td></tr></tbody></table></code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>Dump of assembler code for function add:
   0x0000555555561389 &lt;+0&gt;:	f3 0f 1e fa	endbr64
   0x000055555556138d &lt;+4&gt;:	55	push   %rbp
   0x000055555556138e &lt;+5&gt;:	48 89 e5	mov    %rsp,%rbp
   0x0000555555561391 &lt;+8&gt;:	48 83 ec 10	sub    $0x10,%rsp
   0x0000555555561395 &lt;+12&gt;:	89 7d fc	mov    %edi,-0x4(%rbp)
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This is the disassembly of the unaltered target function. <code class="language-plaintext highlighter-rouge">12</code> bytes for the <code class="language-plaintext highlighter-rouge">JMP</code>
patch will have to be written at this address. Therefore the first <code class="language-plaintext highlighter-rouge">4</code>
instructions will need to be written to the trampoline function followed by a
<code class="language-plaintext highlighter-rouge">JMP</code> to address <code class="language-plaintext highlighter-rouge">0x0000555555561395</code> and that’s all we need for the trampoline!</p>

<p>Now the fun part! Let’s continue execution to the next breakpoint, where our
<code class="language-plaintext highlighter-rouge">JMP</code> hook will be placed.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>continue
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Let’s examine the disassembly of our <code class="language-plaintext highlighter-rouge">add()</code> function once again:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>Dump of assembler code for function add:
   0x0000555555561389 &lt;+0&gt;: 48 b8 b1 13 56 55 55 55 00 00 movabs $0x5555555613b1,%rax
   0x0000555555561393 &lt;+10&gt;: ff e0	jmpq   *%rax
   0x0000555555561395 &lt;+12&gt;: 89 7d fc	mov    %edi,-0x4(%rbp)
   0x0000555555561398 &lt;+15&gt;: 89 75 f8	mov    %esi,-0x8(%rbp)
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">0x5555555613b1</code> is the address of our detour/intercept function. Let’s examine
the disassembly of our detour function:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>disas /r 0x5555555613b1
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre>Dump of assembler code for function add_detour:
   0x00005555555613b1 &lt;+0&gt;:	f3 0f 1e fa	endbr64
   0x00005555555613b5 &lt;+4&gt;:	55	push   %rbp
   0x00005555555613b6 &lt;+5&gt;:	48 89 e5	mov    %rsp,%rbp
   0x00005555555613b9 &lt;+8&gt;:	48 83 ec 10	sub    $0x10,%rsp
   0x00005555555613bd &lt;+12&gt;:	89 7d fc	mov    %edi,-0x4(%rbp)
   0x00005555555613c0 &lt;+15&gt;:	89 75 f8	mov    %esi,-0x8(%rbp)
   0x00005555555613c3 &lt;+18&gt;:	48 8d 3d 53 5c 00 00	lea    0x5c53(%rip),%rdi
   0x00005555555613ca &lt;+25&gt;:	e8 b1 fd ff ff	callq  0x555555561180 &lt;puts@plt&gt;
   0x00005555555613cf &lt;+30&gt;:	48 8b 05 ba bc 01 00	mov    0x1bcba(%rip),%rax
   0x00005555555613d6 &lt;+37&gt;:	be 05 00 00 00	mov    $0x5,%esi
   0x00005555555613db &lt;+42&gt;:	bf 05 00 00 00	mov    $0x5,%edi
   0x00005555555613e0 &lt;+47&gt;:	ff d0	callq  *%rax
   0x00005555555613e2 &lt;+49&gt;:	c9	leaveq
   0x00005555555613e3 &lt;+50&gt;:	c3	retq
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We can see that a call to our trampoline function is made to the address given
by referencing the <code class="language-plaintext highlighter-rouge">QWORD</code> (out function pointer) at address <code class="language-plaintext highlighter-rouge">0x55555557d090</code>,
let’s deference it:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>print /x *(long unsigned int*)(0x55555557d090)
</pre></td></tr></tbody></table></code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>$20 = 0x7ffff7ffb000
</pre></td></tr></tbody></table></code></pre></div></div>

<p>So the function pointer is pointing to address <code class="language-plaintext highlighter-rouge">0x7ffff7ffb000</code> which is our
trampoline function, let’s dissasemble it:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>x/10i 0x7ffff7ffb000
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre>   0x7ffff7ffb000:	endbr64
   0x7ffff7ffb004:	push   %rbp
   0x7ffff7ffb005:	mov    %rsp,%rbp
   0x7ffff7ffb008:	sub    $0x10,%rsp
   0x7ffff7ffb00c:	movabs $0x555555561395,%rax
   0x7ffff7ffb016:	jmpq   *%rax
   0x7ffff7ffb018:	add    %al,(%rax)
   0x7ffff7ffb01a:	add    %al,(%rax)
   0x7ffff7ffb01c:	add    %al,(%rax)
   0x7ffff7ffb01e:	add    %al,(%rax)
</pre></td></tr></tbody></table></code></pre></div></div>

<p>You can see that our trampoline contains the first <code class="language-plaintext highlighter-rouge">4</code> instructions that were
replaced when the <code class="language-plaintext highlighter-rouge">JMP</code> patch was placed in our target function. You can see a
jmp back to address <code class="language-plaintext highlighter-rouge">0x555555561395</code> which was disassembled earlier. This should
give you an idea of how the control flow modification is achieved.</p>

<h1 id="int3-patching">INT3 Patching</h1>

<p>There is another method of function detouring which involves placing <code class="language-plaintext highlighter-rouge">INT3</code>
breakpoints at the start of the target function in memory. <code class="language-plaintext highlighter-rouge">INT3</code> breakpoints
are encoded with the <code class="language-plaintext highlighter-rouge">0xCC</code> opcode:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>/* Generate int3 instruction. */
uint8_t *cdl_gen_swbp(uint8_t *code)
{
    *(code + 0x0) = 0xCC;
    return code;
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>So rather than placing a <code class="language-plaintext highlighter-rouge">JMP</code> patch to the detour we simply write the byte
<code class="language-plaintext highlighter-rouge">0xCC</code> to the target function being careful to <code class="language-plaintext highlighter-rouge">NOP</code> the unused bytes. Once the
<code class="language-plaintext highlighter-rouge">RIP</code> register reaches an address of an <code class="language-plaintext highlighter-rouge">INT3</code> breakpoint the Linux kernel sends
a <code class="language-plaintext highlighter-rouge">SIGTRAP</code> signal to the process.</p>

<p>We can register our own signal handler but we need some additional info on the
signal such as context information. A context is the state of a program’s
registers and stack. We need this info to compare the breakpoints <code class="language-plaintext highlighter-rouge">RIP</code> value to
any active global software breakpoints.</p>

<p>This is how the signal handler is registered in <code class="language-plaintext highlighter-rouge">cdl86</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre> struct sigaction sa = {};

    /* Initialise cdl signal handler. */
    if (!cdl_swbp_init)
    {
        /* Request signal context info which
         * is required for RIP register comparison.
         */
        sa.sa_flags = SA_SIGINFO | SA_ONESHOT;
        sa.sa_sigaction = (void *)cdl_swbp_handler;
        sigaction(SIGTRAP, &amp;sa, NULL);
        cdl_swbp_init = true;
    }
    ...
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Note the use of <code class="language-plaintext highlighter-rouge">SA_SIGINFO</code> to get context information. The software breakpoint
handler is then defined as follows:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="rouge-code"><pre>void cdl_swbp_handler(int sig, siginfo_t *info, struct ucontext_t *context)
{
    int i = 0x0;
    bool active = false;
    uint8_t *bp_addr = NULL;

    /* RIP register point to instruction after the
     * int3 breakpoint so we subtract 0x1.
     */
    bp_addr = (uint8_t *)(context-&gt;uc_mcontext.gregs[REG_RIP] - 0x1);

    /* Iterate over all breakpoint structs. */
    for (i = 0; i &lt; cdl_swbp_size; i++)
    {
        active = cdl_swbp_hk[i].active;
        /* Compare breakpoint addresses. */
        if (bp_addr == cdl_swbp_hk[i].bp_addr)
        {
            /* Update RIP and reset context. */
            context-&gt;uc_mcontext.gregs[REG_RIP] = (greg_t)cdl_swbp_hk[i].detour;
            setcontext(context);
        }
    }
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Note that if a match of the <code class="language-plaintext highlighter-rouge">RIP</code> value to any known breakpoints occurs the <code class="language-plaintext highlighter-rouge">RIP</code>
value for the current context is updated and the new context applied using
<code class="language-plaintext highlighter-rouge">setcontext()</code>. A trampoline function similar to our <code class="language-plaintext highlighter-rouge">JMP</code> patch is allocated
and serves the same purpose.</p>

<h1 id="code-injection">Code Injection</h1>

<p><code class="language-plaintext highlighter-rouge">cdl86</code> assumes that you are operating in the address space of the target
process. Therefore code injection is often required in practice and requires the
use of an
<a href="https://github.com/lunar-sh/robocraft/tree/main/injector">injector</a>.</p>

<p>Once a shared library (<code class="language-plaintext highlighter-rouge">.so</code>) has been injected you can use the following code
to get the base address of the main executable module:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre>#include &lt;link.h&gt;
#include &lt;inttypes.h&gt;

int __attribute__((constructor)) init()
{
...
    struct link_map *lm = dlopen(0, RTLD_NOW);
    printf("base = %" PRIx64 , lm-&gt;l_addr);
...

}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Or find the address of a function by symbol name:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>void* dl_handle = dlopen(NULL, RTLD_LAZY);
void* add_ptr = dlsym(dl_handle, "add");
</pre></td></tr></tbody></table></code></pre></div></div>

<h1 id="api">API</h1>
<p>The API for the <code class="language-plaintext highlighter-rouge">cdl86</code> library is shown below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>struct cdl_jmp_patch cdl_jmp_attach(void **target, void *detour);
struct cdl_swbp_patch cdl_swbp_attach(void **target, void *detour);
void cdl_jmp_detach(struct cdl_jmp_patch *jmp_patch);
void cdl_swbp_detach(struct cdl_swbp_patch *swbp_patch);
void cdl_jmp_dbg(struct cdl_jmp_patch *jmp_patch);
void cdl_swbp_dbg(struct cdl_swbp_patch *swbp_patch);
</pre></td></tr></tbody></table></code></pre></div></div>

<h1 id="source-code">Source code</h1>
<p>You can find the <code class="language-plaintext highlighter-rouge">cdl86</code> source code
<a href="https://github.com/lunar-sh/cdl86">here</a>.<br /></p>

<h1 id="signature">Signature</h1>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="rouge-code"><pre>+---------------------------------------+
|     .-.       .-.       .-.           |
|    /   \     /   \     /   \     +    |
|         \   /     \   /     \   /     |
|          "_"       "_"       "_"      |
|                                       |
|  _   _   _ _  _   _   ___   ___ _  _  |
| | | | | | | \| | /_\ | _ \ / __| || | |
| | |_| |_| | .` |/ _ \|   /_\__ \ __ | |
| |____\___/|_|\_/_/ \_\_|_(_)___/_||_| |
|                                       |
|                                       |
| Lunar RF Labs                         |
| Email: root@lunar.sh                  |
|                                       |
| Research Laboratories                 |
| OpenAlias (BTC, XMR): lunar.sh        |
| Copyright (C) 2022-2024               |
+---------------------------------------+
</pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name>Dylan Müller</name></author><summary type="html"><![CDATA[Function detouring is a powerful hooking technique that allows for the interception of C/C++ functions. cdl86 aims to be a tiny C detours library for x86_64 binaries.]]></summary></entry><entry><title type="html">Mono/.NET Injection Under Linux</title><link href="https://journal.lunar.sh/2020/mono-dot-net-injection.html" rel="alternate" type="text/html" title="Mono/.NET Injection Under Linux" /><published>2020-12-11T00:00:00+00:00</published><updated>2020-12-11T00:00:00+00:00</updated><id>https://journal.lunar.sh/2020/mono-dot-net-injection</id><content type="html" xml:base="https://journal.lunar.sh/2020/mono-dot-net-injection.html"><![CDATA[<blockquote>
  <p>Learning <code class="language-plaintext highlighter-rouge">mono</code> or <code class="language-plaintext highlighter-rouge">C#</code> library injection through a Robocraft exploit. The method used in
this publication can be used to modify a wide range of Unity games.</p>
</blockquote>

<ol>
  <li><a href="#mono-overview">Mono Overview</a></li>
  <li><a href="#exploiting-robocraft">Exploiting Robocraft</a></li>
  <li><a href="#source-code">Source Code</a></li>
</ol>

<h1 id="mono-overview">Mono Overview</h1>

<p><a href="https://en.wikipedia.org/wiki/Mono_%28software%29">Mono</a> is an open source port
of the <code class="language-plaintext highlighter-rouge">.NET</code> framework which runs on a variety of operating systems (including
Linux).</p>

<p>The <code class="language-plaintext highlighter-rouge">mono</code> build chain compiles <code class="language-plaintext highlighter-rouge">C#</code> source code (<code class="language-plaintext highlighter-rouge">.cs</code> files) down to <code class="language-plaintext highlighter-rouge">IL</code> (immediate
language) spec’d byte code which is then executed by the <code class="language-plaintext highlighter-rouge">CLR</code> (Common Language
Runtime) layer provided by <code class="language-plaintext highlighter-rouge">mono</code>.</p>

<p>Due to the translation down to <code class="language-plaintext highlighter-rouge">IL</code>, module decompilation as well as
modification/reverse engineering is relatively straightforward and a variety of
<code class="language-plaintext highlighter-rouge">C#</code> <code class="language-plaintext highlighter-rouge">IL</code> decompilers/recompilers already exist
(<a href="https://github.com/dnSpy/dnSpy/">dnSpy</a>,
<a href="https://github.com/icsharpcode/ILSpy">ILSpy</a>).</p>

<p>The focus of this journal is on managed library injection, more specifically the
ability to inject <code class="language-plaintext highlighter-rouge">C#</code> code of our own and interact with/modify a target host.</p>

<h1 id="exploiting-robocraft">Exploiting Robocraft</h1>

<p><a href="https://en.wikipedia.org/wiki/Robocraft">Robocraft</a> is an online <code class="language-plaintext highlighter-rouge">MMO</code> game
developed by <code class="language-plaintext highlighter-rouge">freejam</code> games. It features futuristic robotic battles and is an
example of an application we wish to tamper with.</p>

<p><img src="https://journal.lunar.sh/images/4/01.jpg" alt="enter image description here" /></p>

<p><code class="language-plaintext highlighter-rouge">Robocraft</code> uses the <a href="https://unity3d.com/get-unity/download">Unity3D</a> engine,
which is a high level <code class="language-plaintext highlighter-rouge">C#</code> component based game engine.</p>

<p>World entities in <code class="language-plaintext highlighter-rouge">Unity3D</code> derive from class <code class="language-plaintext highlighter-rouge">UnityEngine::GameObject</code> and may
have a number of components attached to them such as: rigidbodies, mesh
renderers, scripts, etc.</p>

<p><code class="language-plaintext highlighter-rouge">UnityEngine::GameObject</code> has many useful
<a href="https://docs.unity3d.com/ScriptReference/GameObject.html">properties</a> such as a
name (string), tag, transform (position), etc. as well as static methods for
finding objects by name, tag, etc. These methods become useful when injecting
our own code as they provide a facility for interfacing with the game engine
from an external context (our <code class="language-plaintext highlighter-rouge">C#</code> script).</p>

<p>Browsing the <code class="language-plaintext highlighter-rouge">Robocraft</code> root directory (installed via steam) revealed a few
directories that seemed interesting:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Robocraft_Data</code></li>
  <li><code class="language-plaintext highlighter-rouge">lib64</code></li>
  <li><code class="language-plaintext highlighter-rouge">lib32</code></li>
  <li><code class="language-plaintext highlighter-rouge">EasyAntiCheat</code></li>
</ul>

<p><img src="https://journal.lunar.sh/images/4/02.png" alt="enter image description here" /></p>

<p>Upon further inspection of the <code class="language-plaintext highlighter-rouge">Robocraft_Data</code> directory, we find the folders
containing the managed (<code class="language-plaintext highlighter-rouge">C#/mono</code>) portion of the application. In particular, the
Managed folder contains the <code class="language-plaintext highlighter-rouge">C#</code> libraries in <code class="language-plaintext highlighter-rouge">DLL</code> form of the <code class="language-plaintext highlighter-rouge">Unity3D</code> Engine as well
as other proprietary modules from the game developer.</p>

<p><img src="https://journal.lunar.sh/images/4/03.png" alt="enter image description here" /></p>

<p>However at his point it’s worth noting the presence of the <code class="language-plaintext highlighter-rouge">EasyAntiCheat</code> folder
in the root game directory which confirms the presence of an <code class="language-plaintext highlighter-rouge">anti-cheat</code> client.</p>

<p>After some research I found out a few interesting details about the game’s
<code class="language-plaintext highlighter-rouge">anti-cheat</code> client <code class="language-plaintext highlighter-rouge">EasyAntiCheat</code>:</p>

<ul>
  <li>The client computes hashes of all binary images during startup (including
managed libraries) and is cross-referenced to prevent modification to game
binaries.</li>
  <li>Uses a heartbeat mechanism to ensure presence of the <code class="language-plaintext highlighter-rouge">anti-cheat</code> client (To
mitigate <code class="language-plaintext highlighter-rouge">anti-cheat</code> removal).</li>
  <li>Works with an online service known as <code class="language-plaintext highlighter-rouge">RoboShield</code> to monitor server side
parameters such as position, velocity, damage, etc and assigns each user with
a trust score. The lower the score the higher the chance of getting kicked
from subsequent matches. This score seems to be persistent.</li>
</ul>

<p>Nonetheless, nothing seemed to prevent us from injecting our own <code class="language-plaintext highlighter-rouge">C#</code> library at
runtime and this was the vector employed with <code class="language-plaintext highlighter-rouge">Robocraft</code>. The advantage of this
method was that no modification to the game binaries would be required and
therefore any client side anti-tamper protection could be bypassed.</p>

<p>In order to inject our own <code class="language-plaintext highlighter-rouge">C#</code> code we need to somehow force the client to load
our own <code class="language-plaintext highlighter-rouge">.NET/mono</code> library at runtime. This may be accomplished by a stager
payload which is essentially a shared library that makes internal calls to
<code class="language-plaintext highlighter-rouge">libmono.so</code>.</p>

<p>Some interesting symbols found in <code class="language-plaintext highlighter-rouge">libmono.so</code> include:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">mono_get_root_domain</code> - get handle to primary domain.</li>
  <li><code class="language-plaintext highlighter-rouge">mono_thread_attach</code> - attach to domain.</li>
  <li><code class="language-plaintext highlighter-rouge">mono_assembly_open</code> - load assembly.</li>
  <li><code class="language-plaintext highlighter-rouge">mono_assembly_get_image</code> - get assembly image.</li>
  <li><code class="language-plaintext highlighter-rouge">mono_class_from_name</code> - get handle to class.</li>
  <li><code class="language-plaintext highlighter-rouge">mono_class_get_method_from_name</code> - get handle to class method.</li>
  <li><code class="language-plaintext highlighter-rouge">mono_runtime_invoke</code> - invoke class method.</li>
</ul>

<p>The function signatures for these symbols are shown below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre>typedef void* (*mono_thread_attach)(void* domain);
typedef void* (*mono_get_root_domain)();
typedef void* (*mono_assembly_open)(char* file, void* stat);
typedef void* (*mono_assembly_get_image)(void* assembly);
typedef void* (*mono_class_from_name)(void* image, char* namespacee, char* name);
typedef void* (*mono_class_get_method_from_name)(void* classs, char* name, DWORD param_count);
typedef void* (*mono_runtime_invoke)(void* method, void* instance, void* *params, void* exc);
</pre></td></tr></tbody></table></code></pre></div></div>

<p>In order to perform code injection, firstly a handle to the root application
domain must be retrieved using <code class="language-plaintext highlighter-rouge">mono_get_root_domain</code>. The primary application
thread must then be binded to the root domain using <code class="language-plaintext highlighter-rouge">mono_thread_attach</code> and the
assembly image loaded with <code class="language-plaintext highlighter-rouge">mono_assembly_open</code> and <code class="language-plaintext highlighter-rouge">mono_assembly_get_image</code>.</p>

<p>Next the assembly class and class method to execute may be found by name using
<code class="language-plaintext highlighter-rouge">mono_class_from_name</code> and <code class="language-plaintext highlighter-rouge">mono_class_get_method_from_name</code>.</p>

<p>Finally the class method may be executed using <code class="language-plaintext highlighter-rouge">mono_runtime_invoke</code>. It should
be noted that the class method to execute should be declared as static.</p>

<p>The resulting stager payload is shown below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
</pre></td><td class="rouge-code"><pre>#include &lt;iostream&gt;
#include &lt;link.h&gt;
#include &lt;fstream&gt;

using namespace std;

typedef unsigned long DWORD;

typedef void* (*mono_thread_attach)(void* domain);
typedef void* (*mono_get_root_domain)();
typedef void* (*mono_assembly_open)(char* file, void* stat);
typedef void* (*mono_assembly_get_image)(void* assembly);
typedef void* (*mono_class_from_name)(void* image, char* namespacee, char* name);
typedef void* (*mono_class_get_method_from_name)(void* classs, char* name, DWORD param_count);
typedef void* (*mono_runtime_invoke)(void* method, void* instance, void* *params, void* exc);


mono_get_root_domain do_mono_get_root_domain;
mono_assembly_open do_mono_assembly_open;
mono_assembly_get_image do_mono_assembly_get_image;
mono_class_from_name do_mono_class_from_name;
mono_class_get_method_from_name do_mono_class_get_method_from_name;
mono_runtime_invoke do_mono_runtime_invoke;
mono_thread_attach do_mono_thread_attach;

int __attribute__((constructor)) init()
{
        void* library = dlopen("./Robocraft_Data/Mono/x86_64/libmono.so",  RTLD_NOLOAD | RTLD_NOW);

        do_mono_thread_attach = (mono_thread_attach)(dlsym(library, "mono_thread_attach"));
        do_mono_get_root_domain = (mono_get_root_domain)(dlsym(library, "mono_get_root_domain"));
        do_mono_assembly_open = (mono_assembly_open)(dlsym(library, "mono_assembly_open"));
        do_mono_assembly_get_image = (mono_assembly_get_image)(dlsym(library, "mono_assembly_get_image"));
        do_mono_class_from_name = (mono_class_from_name)(dlsym(library, "mono_class_from_name"));
        do_mono_class_get_method_from_name = (mono_class_get_method_from_name)(dlsym(library, "mono_class_get_method_from_name"));
        do_mono_runtime_invoke = (mono_runtime_invoke)(dlsym(library, "mono_runtime_invoke"));


        do_mono_thread_attach(do_mono_get_root_domain());
        void* assembly = do_mono_assembly_open("./Robocraft_Data/Managed/Client.dll", NULL);

        void* Image = do_mono_assembly_get_image(assembly);
        void* MonoClass = do_mono_class_from_name(Image, "Test", "Test");
        void* MonoClassMethod = do_mono_class_get_method_from_name(MonoClass, "Load", 0);

        do_mono_runtime_invoke(MonoClassMethod, NULL, NULL, NULL);

    return 0;
}

void __attribute__((destructor)) shutdown()
{

};
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The stager payload shown above loads the mono assembly located in
<code class="language-plaintext highlighter-rouge">&lt;root&gt;/Robocraft_Data/Managed/Client.dll</code> into memory and executes the class
method Load within the <code class="language-plaintext highlighter-rouge">namespace</code> <code class="language-plaintext highlighter-rouge">Test</code> and <code class="language-plaintext highlighter-rouge">class</code> <code class="language-plaintext highlighter-rouge">Test</code> (<code class="language-plaintext highlighter-rouge">Test::Test::Load</code>).</p>

<p>Load has the following signature: <code class="language-plaintext highlighter-rouge">public  static  void  Load()</code> The stager may
be compiled with: <code class="language-plaintext highlighter-rouge">gcc -fpic -shared stager.cpp -o stager.so</code>.</p>

<p>In order to inject the stager into the target process you may use any standard
Linux shared library injector.</p>

<p>With the capability of loading our own <code class="language-plaintext highlighter-rouge">mono</code> code into the target process, we
need to ensure that our injected <code class="language-plaintext highlighter-rouge">C#</code> code stays persistent, i.e to prevent
de-allocation due to garbage collection.</p>

<p>For <code class="language-plaintext highlighter-rouge">Unity3D</code> this is typically achieved using the following pattern:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="rouge-code"><pre> public class Exploit : MonoBehaviour
	{...}

 public static class Test
    {
        private static GameObject loader;
        public static void Load()
        {
            loader = new GameObject();
            loader.AddComponent&lt;Exploit&gt;();
            UnityEngine.Object.DontDestroyOnLoad(loader);
        }
    }
</pre></td></tr></tbody></table></code></pre></div></div>

<p>It is also worth keeping track of the <code class="language-plaintext highlighter-rouge">mono/.NET</code> assembly versions used in the
original application. Ideally you would want to use an identical <code class="language-plaintext highlighter-rouge">.NET</code> version as
compiling your <code class="language-plaintext highlighter-rouge">C#</code> exploit with the wrong <code class="language-plaintext highlighter-rouge">.NET</code> version can cause your exploit to
fail.</p>

<p>For <code class="language-plaintext highlighter-rouge">Robocraft</code> <code class="language-plaintext highlighter-rouge">.NET</code> <code class="language-plaintext highlighter-rouge">v2.0</code> was required. Finding support for an older version of
<code class="language-plaintext highlighter-rouge">.NET</code> can be difficult as most modern <code class="language-plaintext highlighter-rouge">C#</code> <code class="language-plaintext highlighter-rouge">IDE's</code> do not support such an old target.
A simple solution to this problem is to download an older version of <code class="language-plaintext highlighter-rouge">mono</code>.</p>

<p>At this point the second stage payload (our <code class="language-plaintext highlighter-rouge">C#</code> exploit) can be developed. I
chose to implement three simple functionalities:</p>

<ul>
  <li>Increase/decrease game speed.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>if(Input.GetKeyDown(KeyCode.F2)){
            speedhack =  !speedhack;
            if(speedhack == true){
                Time.timeScale = 3;
            }else{
                Time.timeScale = 1;
            }
        }
</pre></td></tr></tbody></table></code></pre></div></div>

<ul>
  <li>Clip through walls/obstacles.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre>if(Input.GetKeyDown(KeyCode.F3)){
            collision =  !collision;
            GameObject obj = GameObject.Find("Player Machine Root");
            Rigidbody rb = obj.GetComponent&lt;Rigidbody&gt;();
            if(collision == true){
                rb.detectCollisions = false;
            }else{
                rb.detectCollisions = true;
            }
        }
</pre></td></tr></tbody></table></code></pre></div></div>

<p><img src="https://journal.lunar.sh/images/4/05.png" alt="enter image description here" />
<img src="https://journal.lunar.sh/images/4/06.png" alt="enter image description here" /></p>

<ul>
  <li>Place all network entites near player.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="rouge-code"><pre>if(Input.GetKeyDown(KeyCode.F1))
{
    salt = !salt;
    GameObject obj = GameObject.Find("Player Machine Root");
    position = obj.transform.position;

    foreach(GameObject gameObj in GameObject.FindObjectsOfType&lt;GameObject&gt;())
    {
        if(gameObj.name == "centerGameObject")
        {
            GameObject parent = gameObj.transform.parent.gameObject;
            if(parent.name != "Player Machine Root"){
                MonoBehaviour[] comp = parent.GetComponents&lt;MonoBehaviour&gt;();
                foreach (MonoBehaviour c in comp){
                    c.enabled = !salt;

                }
                Vector3 myposition = position;
                parent.transform.position = myposition;

            }

        }
    }
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p><img src="https://journal.lunar.sh/images/4/07.png" alt="enter image description here" /></p>

<p>In order to find the names of the game objects for the main player as well as
network players you can simply iterate through all the global game objects and
dump the corresponding names to a text file.</p>

<h1 id="source-code">Source Code</h1>

<p>All source code for this <code class="language-plaintext highlighter-rouge">journal</code> is hosted at
<a href="https://github.com/lunar-sh/robocraft">https://github.com/lunar-sh/robocraft</a></p>

<h1 id="signature">Signature</h1>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="rouge-code"><pre>+---------------------------------------+
|     .-.       .-.       .-.           |
|    /   \     /   \     /   \     +    |
|         \   /     \   /     \   /     |
|          "_"       "_"       "_"      |
|                                       |
|  _   _   _ _  _   _   ___   ___ _  _  |
| | | | | | | \| | /_\ | _ \ / __| || | |
| | |_| |_| | .` |/ _ \|   /_\__ \ __ | |
| |____\___/|_|\_/_/ \_\_|_(_)___/_||_| |
|                                       |
|                                       |
| Lunar RF Labs                         |
| Email: root@lunar.sh                  |
|                                       |
| Research Laboratories                 |
| OpenAlias (BTC, XMR): lunar.sh        |
| Copyright (C) 2022-2024               |
+---------------------------------------+
</pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name>Dylan Müller</name></author><summary type="html"><![CDATA[Learning mono or C# library injection through a Robocraft exploit. The method used in this publication can be used to modify a wide range of Unity games.]]></summary></entry><entry><title type="html">Transistor Circuit Design For Newbies</title><link href="https://journal.lunar.sh/2020/transistor-design-for-newbies.html" rel="alternate" type="text/html" title="Transistor Circuit Design For Newbies" /><published>2020-11-03T00:00:00+00:00</published><updated>2020-11-03T00:00:00+00:00</updated><id>https://journal.lunar.sh/2020/transistor-design-for-newbies</id><content type="html" xml:base="https://journal.lunar.sh/2020/transistor-design-for-newbies.html"><![CDATA[<blockquote>
  <p><code class="language-plaintext highlighter-rouge">BJTs</code> are important electronic devices that find use in a wide range of
applications. Learn how to design circuits with them.</p>
</blockquote>

<ol>
  <li><a href="#principle-of-operation">Principle of operation</a></li>
  <li><a href="#transistor-as-a-switch">Transistor as a switch</a></li>
  <li><a href="#transistor-as-an-amplifier">Transistor as an amplifier</a></li>
  <li><a href="#ltspice">LTSpice</a></li>
</ol>

<h1 id="principle-of-operation">Principle of Operation</h1>

<p>There are various analogies that you will most likely come across when first
learning about transistors, a useful analogy is that of a mechanically
controlled water valve.</p>

<p><img src="https://journal.lunar.sh/images/3/07.png" alt="enter image description here" width="500px" /></p>

<p>Here it is important to reference the water analogy of current and voltage. In
the water analogy we picture a column of water moving through a pipe.</p>

<p>We define current as the movement of water (<code class="language-plaintext highlighter-rouge">charge</code>) through the pipe (wire), or
in mathematical terms the rate of flow of water (<code class="language-plaintext highlighter-rouge">charge</code>) past a given point with
respect to time:</p>

\[i=\frac{dC}{dt}\]

<p>Voltage is analogous to the pressure differential between two points. For
example, suppose we suspend water in a pipe and then apply a high pressure at
the top and a lower pressure at the bottom. We have just set up a ‘water
potential difference’ between two points and this tends to move water (<code class="language-plaintext highlighter-rouge">charge</code>)
from the higher pressure region (voltage) to the lower pressure region.</p>

<p>The higher the water potential, the faster the column of water (<code class="language-plaintext highlighter-rouge">charge</code>) moves
through the pipe when it has the chance.</p>

<p>In reality, voltage arises due to the presence of electric fields. For a given
electric field between two points, a positive test charge may be placed at any
distance along the electric field lines, that is, its ‘field potential’ varies
and a positive charge placed closer to the positive end of the electric field
feels more repulsion (and therefore has a higher potential to do work) than at
the negative end of the field.</p>

<p>Potential difference (voltage) is just a differential measure of this electric
‘field potential’ or put differently, the capacity of charge to do work in the
presence of an <code class="language-plaintext highlighter-rouge">electric</code> field:</p>

\[V_{f} - V_{i} = -\int \overrightarrow{E} \cdot \overrightarrow{d}s\]

<p>With this in mind the idea of a water valve then makes sense. The valve consists
of three ports, one attached to one end of the pipe, the other port to the end
section of the pipe and then the valve itself, sitting in the middle and
regulating the flow of water between both ends.</p>

<p>By rotating the valve we adjust the water flow rate (current) through the pipe.
This is the basic principle of operation of a transistor. However rather than
applying a mechanical torque, we apply a potential difference at the base to
regulate current flow.</p>

<p>You may think of the degree to which the mechanical valve is open or closed as
proportional to the voltage applied at the base of the transistor. This means
that we can control a potentially larger current through the transistor using a
smaller current through the base (through the application of a base voltage),
this is one of the useful properties of transistors.</p>

<p><img src="https://journal.lunar.sh/images/memes/meme_01.jpg" alt="meme" /></p>

<p>Bipolar Junction Transistors (<code class="language-plaintext highlighter-rouge">BJTs</code>) usually consists of three semiconductor
layers which can be of two types: <code class="language-plaintext highlighter-rouge">n</code> or <code class="language-plaintext highlighter-rouge">p</code>. The individual <code class="language-plaintext highlighter-rouge">silicon</code> layers are
crystalline structures that have what are known as dopants added to them. These
are individual elements (<code class="language-plaintext highlighter-rouge">phosphorus</code>, <code class="language-plaintext highlighter-rouge">boron</code>) added to neutral <code class="language-plaintext highlighter-rouge">silicon</code> (and
replace the corresponding <code class="language-plaintext highlighter-rouge">silicon</code> atoms) in order to change the electrical
properties of the layer.</p>

<p><img src="https://journal.lunar.sh/images/3/10.png" alt="enter image description here" /></p>

<p>For example, <code class="language-plaintext highlighter-rouge">boron</code> <code class="language-plaintext highlighter-rouge">[B]</code> dopant has a valency (number of outer electrons) of <code class="language-plaintext highlighter-rouge">3</code>,
while <code class="language-plaintext highlighter-rouge">silicon</code> has a valency of <code class="language-plaintext highlighter-rouge">4</code>. This means that when <code class="language-plaintext highlighter-rouge">boron</code> and <code class="language-plaintext highlighter-rouge">silicon</code> bond
covalently (sharing of each others electrons) there is a mismatch (<code class="language-plaintext highlighter-rouge">3</code> &lt; <code class="language-plaintext highlighter-rouge">4</code>)
between their valence electrons, leaving a ‘hole’, which needs to be filled with
an electron in order to match <code class="language-plaintext highlighter-rouge">silicon's</code> valency. This results in a crystal
structure with a net positive charge, the <code class="language-plaintext highlighter-rouge">p</code> type layer.</p>

<p>In contrast <code class="language-plaintext highlighter-rouge">phosphorus</code> <code class="language-plaintext highlighter-rouge">[P]</code> dopant has a valency of <code class="language-plaintext highlighter-rouge">5</code>, again there is a mismatch
(<code class="language-plaintext highlighter-rouge">5</code> &gt; <code class="language-plaintext highlighter-rouge">4</code>) with <code class="language-plaintext highlighter-rouge">silicon's</code> valency (<code class="language-plaintext highlighter-rouge">4</code>), allowing for the extra electron of
<code class="language-plaintext highlighter-rouge">phosphorus</code> to move freely through the crystal structure and giving the overall
crystal layer a negative polarity, the <code class="language-plaintext highlighter-rouge">n</code> type layer.</p>

<p>If we were to place an <code class="language-plaintext highlighter-rouge">n</code> region and <code class="language-plaintext highlighter-rouge">p</code> region together we would form an
electronic device known as a diode. A diode is a <code class="language-plaintext highlighter-rouge">2</code> terminal device (with the <code class="language-plaintext highlighter-rouge">n</code>
side connected to the negative terminal (<code class="language-plaintext highlighter-rouge">cathode</code>) and <code class="language-plaintext highlighter-rouge">p</code> side connected to the
positive terminal (<code class="language-plaintext highlighter-rouge">anode</code>) that only allows current flow in one direction.</p>

<p>It is also worth nothing that by placing an <code class="language-plaintext highlighter-rouge">n</code> and <code class="language-plaintext highlighter-rouge">p</code> region next to one another
there is a localised effect at their layer boundary that results in a small
number of electrons (from the <code class="language-plaintext highlighter-rouge">n</code> type region) migrating to the <code class="language-plaintext highlighter-rouge">p</code> type region in
what is known as the depletion region.</p>

<p><img src="https://journal.lunar.sh/images/3/11.jpg" alt="enter image description here" height="300px" /></p>

<p>The migration of electrons from the n type region to the <code class="language-plaintext highlighter-rouge">p</code> type region at the <code class="language-plaintext highlighter-rouge">np</code>
boundary sets up what is known as a barrier potential, a secondary electric
field at the np layer boundary in opposition to the primary <code class="language-plaintext highlighter-rouge">E-field</code> (between <code class="language-plaintext highlighter-rouge">p</code>
and <code class="language-plaintext highlighter-rouge">n</code>).</p>

<p>This is the amount of voltage (<code class="language-plaintext highlighter-rouge">pressure</code>) required to force <code class="language-plaintext highlighter-rouge">n</code> layer electrons
through the <code class="language-plaintext highlighter-rouge">np</code> barrier (the secondary <code class="language-plaintext highlighter-rouge">E-field</code>) where they can flow into the
positive terminal (<code class="language-plaintext highlighter-rouge">anode</code>) of the diode.</p>

<p>It is equivalent to having a water valve initially shut tight and requiring a
torque in order to get water flowing. A typical value for the barrier potential
of garden variety diodes is between <code class="language-plaintext highlighter-rouge">0.3v-0.7v</code>.</p>

<p>A bipolar junction transistor (<code class="language-plaintext highlighter-rouge">BJT</code>) may be viewed as a combination of two diodes
(shown below for an <code class="language-plaintext highlighter-rouge">NPN</code> transistor):</p>

<p><img src="https://journal.lunar.sh/images/3/05.gif" alt="enter image description here" /></p>

<p>An <code class="language-plaintext highlighter-rouge">NPN</code> <code class="language-plaintext highlighter-rouge">BJT</code> transistor has two current paths, one from the collector to emitter
and the other from the base to emitter. The current flow from collector to
emitter represents the water flow in the pipe containing the valve, while the
current flow from base to emitter represents the degree to which the valve is
open or closed.</p>

<p>You might be wondering why conventional (positive) current flows backwards
through the <code class="language-plaintext highlighter-rouge">base-collector</code> diode (from collector to emitter) for an <code class="language-plaintext highlighter-rouge">NPN</code>
transistor. As it turns out, current can actually flow in multiple directions
through a diode. However it takes much more voltage to ‘push’ charge through a
diode in the direction it’s meant to block than in the direction it is meant to
flow.</p>

<p>The ratio of <code class="language-plaintext highlighter-rouge">base-emitter</code> current to <code class="language-plaintext highlighter-rouge">collector-emitter</code> current is known as (\(\beta\))
and is an important consideration in the design of circuits using transistors:</p>

\[I_{c} = \beta I_{B}\]

<p>Both transistor current paths have an associated voltage drop/potential
difference across them.</p>

<p>For the current flow from base to emitter, there is the <code class="language-plaintext highlighter-rouge">base-emitter</code> voltage
drop \(V_{BE}\) and from collector to emitter there is the <code class="language-plaintext highlighter-rouge">collector-emitter</code>
voltage drop \(V_{CE}\) :</p>

<p>The values of \(V_{CE}\), \(V_{BE}\) and \(V_{CB}\) have predictable
values for the three modes of operation of a transistor, these are:</p>

<ul>
  <li><strong>Cut-off</strong> (The transistor acts as an open circuit; valve closed).
\(V_{BE}\) &lt; <code class="language-plaintext highlighter-rouge">0.7V</code></li>
  <li><strong>Saturation</strong> (The transistor acts as a short circuit; valve completely open).
\(V_{BE}\) &gt;= <code class="language-plaintext highlighter-rouge">0.7V</code></li>
  <li><strong>Active</strong> (The transistor acts as an amplifier; valve varies between closed
and completely open).</li>
</ul>

<h1 id="transistor-as-a-switch">Transistor as a switch</h1>

<p>When using a transistor as a switch we place the transistor into one of two
states: cut-off or saturation.</p>

<p>The following switching circuit is usually employed (with an <code class="language-plaintext highlighter-rouge">NPN</code> <code class="language-plaintext highlighter-rouge">BJT</code>) (shown
together with an <code class="language-plaintext highlighter-rouge">LED</code>):</p>

<p><img src="https://journal.lunar.sh/images/3/12.jpg" alt="enter image description here" height="300px" /></p>

<p>The circuit is seen consisting of a base current limiting resistor \(R_{B}\)
as well as a <code class="language-plaintext highlighter-rouge">collector-emitter</code> current limiting resistor \(R_{LIM}\).</p>

<p>\(R_{B}\) serves to set up the correct base current, while \(R_{LIM}\)
serves to limit the maximum current through the <code class="language-plaintext highlighter-rouge">LED</code> (shown in red) when the
transistor is switched fully on (driven into saturation).</p>

<p>To calculate the values for resistors \(R_{B}\) and \(R_{LIM}\) we use
the equation relating base current to collector current defined earlier:</p>

\[I_{c} = \beta I_{B}\]

<p>The first question becomes what collector current \(I_{C}\) we desire. This
value depends on the device/load you are trying to switch on/off. It is worth
noting that when a transistor is switched fully on (is in saturation mode) the
equivalent circuit (simplified) is as follows (shown without the <code class="language-plaintext highlighter-rouge">LED</code>, you can
assume the <code class="language-plaintext highlighter-rouge">LED</code> follows resistor \(R_{C}\)):</p>

<p><img src="https://journal.lunar.sh/images/3/08.jpg" alt="enter image description here" width="450px" /></p>

<p>Thus at the collector a direct connection to ground is made. However this
connection is not perfect and there is an associated voltage drop from collector
to emitter of typically around <code class="language-plaintext highlighter-rouge">0.2v</code> (\(V_{CE}\)) rather than <code class="language-plaintext highlighter-rouge">0v</code>. Determining
the relevant value for \(I_{C}\) is then just a matter how much current your
load (<code class="language-plaintext highlighter-rouge">LED</code>in our case) requires.</p>

<p>For example, a typical green led requires around <code class="language-plaintext highlighter-rouge">15mA</code> of current to light up
brightly so we set \(I_{C}\) = <code class="language-plaintext highlighter-rouge">15mA</code>. A green <code class="language-plaintext highlighter-rouge">LED</code> also typically has a <code class="language-plaintext highlighter-rouge">2v</code>
drop across it. To calculate \(R_{LIM}\) we use ohms law:</p>

\[R_{LIM} = \frac{V_{CC} - V_{LED} - V_{CE}}{I_{DESIRED}}\]

<p>Given the <code class="language-plaintext highlighter-rouge">LED</code> and collector to emitter voltage drops of <code class="language-plaintext highlighter-rouge">2v</code> and <code class="language-plaintext highlighter-rouge">0.2v</code>
respectively, we can further reduce the above expression above to:</p>

\[R_{LIM} = \frac{V_{CC} - 2 - 0.2}{15 \cdot 10^{-3}}\]

<p>Choosing \(V_{CC}\) is just a matter of what you have at hand. For example,
a <code class="language-plaintext highlighter-rouge">5v</code> or <code class="language-plaintext highlighter-rouge">9v</code> supply would be adequate to drive the transistor into saturation as
long as \(V_{CC} &gt;\) <code class="language-plaintext highlighter-rouge">0.7v</code> (due to the base emitter voltage drop) and \(V_{CC} &gt;\)
<code class="language-plaintext highlighter-rouge">2v</code> (for the led).</p>

<p>Assume \(V_{CC}\) = <code class="language-plaintext highlighter-rouge">5v</code>, then \(R_{LIM}\) = <code class="language-plaintext highlighter-rouge">186.7</code> \(\Omega\)</p>

<p>In calculating the required base current, we use the transistor’s \(\beta\) value. This
can be found on the transistors datasheet and typically varies from anywhere
between <code class="language-plaintext highlighter-rouge">20</code> to <code class="language-plaintext highlighter-rouge">200</code>. The rule of thumb is to use the minimum value of \(\beta\) for a
specific transistor type. For the standard garden variety <code class="language-plaintext highlighter-rouge">2N2222</code> transistor, the
minimum value of \(\beta\) is around <code class="language-plaintext highlighter-rouge">75</code>. Therefore to calculate \(I_{B}\), we have:</p>

\[I_{B} = \frac{I_{C} \cdot SF}{\beta_{min}} = \frac{15mA \cdot 5}{75} = 1mA\]

<p>You might have noticed an additional factor called <code class="language-plaintext highlighter-rouge">SF</code> for (safety factor). This
is a factor typically around <code class="language-plaintext highlighter-rouge">5-10</code> that we multiply our calculated \(I_{B}\)
with in order to ensure we drive the transistor into saturation. This gives a
value of around <code class="language-plaintext highlighter-rouge">1mA</code> for \(I_{B}\).</p>

<p>Given \(I_{B}\), calculating \(R_{B}\) becomes trivial as we know the
voltage across \(R_{B}\) as: \(V_{CC} - V_{BE}\) (think of
\(V_{BE}\) as a <code class="language-plaintext highlighter-rouge">0.7v</code> diode) and so we apply ohms law once again:</p>

\[R_{B} = \frac{V_{CC} - V_{BE}}{I_{B}} = \frac{5-0.7}{1 \cdot 10^{-3}} = 4.3k\Omega\]

<p>Now you can connect a switch between the base resistor and Vcc or connect the
base resistor directly to the output of a <code class="language-plaintext highlighter-rouge">5V-TTL</code> micro-controller in order to
turn the <code class="language-plaintext highlighter-rouge">LED</code> on and off! The benefit of using a transistor to do that is that we
require a relatively small current (<code class="language-plaintext highlighter-rouge">&lt; 1mA</code>) in order to switch a much larger
current through the <code class="language-plaintext highlighter-rouge">LED</code> (<code class="language-plaintext highlighter-rouge">15mA</code>)!</p>

<p>In conclusion:</p>
<ol>
  <li>Determine required collector current \(I_{C}\).</li>
  <li>Calculate \(R_{LIM}\) (ohms law).</li>
  <li>Calculate \(I_{B}\) using lowest value for \(\beta\).</li>
  <li>Multiply \(I_{B}\) by safety factor <code class="language-plaintext highlighter-rouge">5-10</code>.</li>
  <li>Calculate \(R_{B}\) (ohms law).</li>
</ol>

<p>The simple <code class="language-plaintext highlighter-rouge">LED</code> transistor circuit was modelled in <code class="language-plaintext highlighter-rouge">LTSpice</code>, with the <code class="language-plaintext highlighter-rouge">LED</code>
represented as a series voltage source (representing the <code class="language-plaintext highlighter-rouge">2v</code> voltage drop).:</p>

<p><img src="https://journal.lunar.sh/images/3/18.png" alt="enter image description here" width="400px" /></p>

<p>A simulation of the <code class="language-plaintext highlighter-rouge">DC</code> operating point of the circuit yielded:</p>

<p><img src="https://journal.lunar.sh/images/3/19.png" alt="enter image description here" height="200px" /></p>

<p>Here we can see the <code class="language-plaintext highlighter-rouge">~1mA</code> base current (\(I_{b}\)) driving <code class="language-plaintext highlighter-rouge">~15mA</code> collector
(\(I_{C}\)) current. All current values are shown in <code class="language-plaintext highlighter-rouge">S.I</code> units of amperes
(<code class="language-plaintext highlighter-rouge">A</code>).</p>

<h1 id="transistor-as-an-amplifier">Transistor as an amplifier</h1>

<p>Here we operate the transistor in its active mode to achieve linear
amplification. Linear amplification means that our output should be a
proportional scaling of our input. For example if we feed in a sine wave we
should ideally get a scaled sine wave out, i.e with no distortion/clipping.</p>

<p>There are various circuit configurations used to achieve amplification using
transistors, a useful ‘template’ is known as common emitter configuration (shown
below with an <code class="language-plaintext highlighter-rouge">NPN</code> transistor):</p>

<p><img src="https://journal.lunar.sh/images/3/37.png" alt="enter image description here" width="600px" /></p>

<p>Here we model a <code class="language-plaintext highlighter-rouge">20 mVp</code> (20mV amplitude) sinusoidal signal source with a
resistance of <code class="language-plaintext highlighter-rouge">50</code> \(\Omega\), but your input can be practically anything.</p>

<p>It should be noted that there are two electrical ‘components’ of the above
circuit, these are <code class="language-plaintext highlighter-rouge">AC</code> (the fluctuating component) and <code class="language-plaintext highlighter-rouge">DC</code> (the static component).</p>

<p>When analysing a circuit from a <code class="language-plaintext highlighter-rouge">DC</code> perspective there are a few rules to follow:</p>
<ul>
  <li>Capacitors become open circuits.</li>
  <li>Inductors become closed circuits.</li>
</ul>

<p>This means that at the base of <code class="language-plaintext highlighter-rouge">Q1</code>, <code class="language-plaintext highlighter-rouge">C3</code> becomes an open connection, i.e the base
of the transistor cannot see signal source <code class="language-plaintext highlighter-rouge">V2</code> or the <code class="language-plaintext highlighter-rouge">50</code> \(\Omega\). resistor.
Additionally, capacitor <code class="language-plaintext highlighter-rouge">C1</code> becomes an open circuit and therefore has no effect
(it’s as if all the capacitors weren’t there in the first place).</p>

<p>Capacitor <code class="language-plaintext highlighter-rouge">C3</code> is known as a <code class="language-plaintext highlighter-rouge">DC</code> blocking capacitor and is used to remove the <code class="language-plaintext highlighter-rouge">DC</code>
component of the input signal at the feed point (base of <code class="language-plaintext highlighter-rouge">Q1</code>). All signals have a
<code class="language-plaintext highlighter-rouge">DC</code> component:</p>

<p><img src="https://journal.lunar.sh/images/3/21.png" alt="enter image description here" height="300px" /></p>

<p>Effectively <code class="language-plaintext highlighter-rouge">C3</code> serves to isolate the fluctuating (<code class="language-plaintext highlighter-rouge">AC</code>) component from the net
signal, that is, we need a signal that moves along the line <code class="language-plaintext highlighter-rouge">y = 0</code>.</p>

<p>Capacitor <code class="language-plaintext highlighter-rouge">C2</code> is also a <code class="language-plaintext highlighter-rouge">DC</code> blocking capacitor and also serves to remove any <code class="language-plaintext highlighter-rouge">DC</code>
offset at the output of the amplifier.</p>

<p>The role of capacitor <code class="language-plaintext highlighter-rouge">C1</code> is a bit more involved and requires and understanding
of <code class="language-plaintext highlighter-rouge">AC</code> circuit analysis, specifically the <code class="language-plaintext highlighter-rouge">AC</code> signal gain/amplification
\(A_{v}\) which, for common emitter configuration, is given by:</p>

\[A_{v} = \frac{z_{out}}{r'e + R_{e}}\]

<p>Here \(z_{out}\) represents the output impedance of the common-emitter
amplifier which is given by the parallel combination of \(R_{c}\) and your
load resistance, \(R_{L}\) (connected to <code class="language-plaintext highlighter-rouge">C2</code>).</p>

\[z_{out} = \frac{R_{c} \cdot R_{L}}{R_{c} + R_{L}}\]

<p>From an <code class="language-plaintext highlighter-rouge">AC</code> perspective:</p>
<ul>
  <li>Capacitors become short circuits.</li>
  <li>Inductors become open circuits.</li>
  <li>Voltage sources become grounds.</li>
</ul>

<p>The term \(r'e\) is known as the transistor’s <code class="language-plaintext highlighter-rouge">AC</code> base-emitter junction resistance
and is given by:</p>

\[r'e = \frac{25mV}{I_{E}}\]

<p>The introduction of capacitor <code class="language-plaintext highlighter-rouge">C1</code> nulls out the term \(R_{e}\) from the
expression for  \(A_{v}\). This is typically done to achieve higher values
of \(A_{v}\) than would otherwise be possible if resistor \(R_{e}\) was
still present. For lower, more controlled values of \(A_{v}\), resistor
\(R_{e}\) should not be bypassed by capacitor <code class="language-plaintext highlighter-rouge">C1</code>.</p>

<p>The first step in the design of the amplifier is choosing \(R_{c}\) such that
\(z_{out}\) isn’t affected by changes in \(R_{L}\). For example, for a
large value of \(R_{L}\) choose \(R_{c} \ll R_{L}\).</p>

<p>For the purposes of our example we assume \(R_{L}\) = <code class="language-plaintext highlighter-rouge">100</code> \(k\Omega\). We then choose
\(R_{c}\) = <code class="language-plaintext highlighter-rouge">5</code> \(k\Omega\)</p>

<p>Next we determine the maximum <code class="language-plaintext highlighter-rouge">AC</code> gain possible given a fixed \(z_{out}\) :</p>

\[A_{v} = \frac{0.7(\frac{V_{CC}}{2})}{0.025}\]

<p>It is usually good practice to give <code class="language-plaintext highlighter-rouge">30%</code> of \(\frac{V_{CC}}{2}\) to \(R_{e}\) and <code class="language-plaintext highlighter-rouge">70%</code> to \(R_{c}\). Higher
ratios of \(V_{CC}(R_{e})\) to \(V_{CC}(R_{c})\) might lead to higher <code class="language-plaintext highlighter-rouge">AC</code> gain (\(A_{v}\)) but
could sacrifice operational stability as a result.</p>

<p>Given \(V_{CC}\) = <code class="language-plaintext highlighter-rouge">5V</code>, we get \(A_{v}\) = <code class="language-plaintext highlighter-rouge">70</code>. This is the highest
expected voltage gain for this amplifier.</p>

<p>We know that:</p>

\[I_{E} \approx I_{C} \approx \frac{0.025 A_{v}}{z_{out}}\]

<p>Thus, given \(A_{v}\) = <code class="language-plaintext highlighter-rouge">70</code>, \(z_{out}\) = <code class="language-plaintext highlighter-rouge">5</code> \(k\Omega\) we have \(I_{E}\) =
<code class="language-plaintext highlighter-rouge">0.35mA</code>. We are now able to calculate \(R_{e}\) :</p>

\[R_{e} = \frac{0.3(\frac{V_{CC}}{2})}{I_{E}}\]

<p>For \(V_{CC}\) = <code class="language-plaintext highlighter-rouge">5V</code>, \(I_{E}\) = <code class="language-plaintext highlighter-rouge">0.35mA</code> we get  \(R_{e} \approx\) <code class="language-plaintext highlighter-rouge">2.1</code> \(k\Omega\).</p>

<p>A useful parameter for common emitter configuration is the <code class="language-plaintext highlighter-rouge">AC</code> input impedance
(looking in from <code class="language-plaintext highlighter-rouge">C3</code>) and is given by:</p>

\[z_{in} = (\frac{1}{R_{1}} + \frac{1}{R_{2}} + \frac{1}{R_{base}})^{-1}\]

<p>Here \(R_{base}\) represents the AC input impedance of transistor <code class="language-plaintext highlighter-rouge">Q1</code>
(looking into the base):</p>

\[R_{base} = \beta \cdot r'e\]

<p>We know how to calculate <code class="language-plaintext highlighter-rouge">r'e</code> from earlier and we use the minimum value of \(\beta\) (<code class="language-plaintext highlighter-rouge">75</code>
for <code class="language-plaintext highlighter-rouge">2N2222</code>) to calculate \(R_{base}\) :</p>

\[R_{base} = 75 \cdot \frac{25}{0.35}\]

<p>Thus \(R_{base}\) = <code class="language-plaintext highlighter-rouge">5.4</code> \(k\Omega\)</p>

<p>Returning to our <code class="language-plaintext highlighter-rouge">DC</code> analysis, we calculate the expected voltage at the
transistor base:</p>

\[V_{B} = V_{Re} + 0.7\]

<p>We know that \(V_{Re}\) is <code class="language-plaintext highlighter-rouge">30%</code> of \(\frac{V_{CC}}{2}\), which gives \(V_{B}\) = <code class="language-plaintext highlighter-rouge">1.45V</code>.
Now given \(I_{E}\) = <code class="language-plaintext highlighter-rouge">0.35mA</code> we can again use our minimum value for \(\beta\) to
calculate our required base current:</p>

\[I_{B} = \frac{0.35 mA}{75}\]

<p>Thus \(I_{B}\) = <code class="language-plaintext highlighter-rouge">4.57uA</code></p>

<p>At this point we need to ensure that small changes in the value of base current
(which occur due to variations in \(\beta\)) do not significantly effect the <code class="language-plaintext highlighter-rouge">DC</code>
operating point of the amplifier circuit.</p>

<p>In order to ensure a stable operating point we ‘stiffen’ the voltage divider by
ensuring the only a small fraction of the total resistor divider current flows
into the base of transistor <code class="language-plaintext highlighter-rouge">Q1</code>.</p>

<p>A good rule of thumb is to allow for <code class="language-plaintext highlighter-rouge">1%</code> of the total divider current to pass
into the base of the transistor.</p>

\[\frac{1}{100} \cdot I_{R_{1}} = 4.57uA\]

<p>We can therefore assume that \(I_{R1} \approx I_{R2}\) and solving the
above expression yields \(I_{R2}\) = <code class="language-plaintext highlighter-rouge">0.456mA</code>. Since we know the voltage
across  \(R_{2}\) (given by \(V_{B}\)) we can calculate the resistance
value:</p>

\[R_{2} = \frac{1.45}{0.99(0.456 \cdot 10^{-3})}\]

<p>This gives \(R_{2} \approx\) <code class="language-plaintext highlighter-rouge">3.2</code> \(k\Omega\). Finally we calculate the value of
\(R_{1}\) :</p>

\[R_{1} = \frac{5-1.45}{0.456 \cdot 10^{-3}}\]

<p>\(R_{1} \approx\) <code class="language-plaintext highlighter-rouge">7.8</code> \(k\Omega\)</p>

<p>The values of capacitors <code class="language-plaintext highlighter-rouge">C3</code>, <code class="language-plaintext highlighter-rouge">C2</code> and <code class="language-plaintext highlighter-rouge">C1</code> are chosen such that the capacitive
reactance (resistance at <code class="language-plaintext highlighter-rouge">AC</code>) at the desired signal frequency is minimal.</p>

<p>Capacitive reactance is given by:</p>

\[X_{C} = \frac{1}{2\pi fC}\]

<p>Now that we have all the required component values, we build the circuit in
<code class="language-plaintext highlighter-rouge">LTSpice</code>:</p>

<p><img src="https://journal.lunar.sh/images/3/38.png" alt="enter image description here" /></p>

<p>A simulation of the <code class="language-plaintext highlighter-rouge">DC</code> operating point was performed:</p>

<p><img src="https://journal.lunar.sh/images/3/40.png" alt="enter image description here" width="500px" /></p>

<p>Here we can see our expected \(V_{base}\) of around <code class="language-plaintext highlighter-rouge">1.45V</code> and an emitter
current of around <code class="language-plaintext highlighter-rouge">0.38mA</code> (instead of <code class="language-plaintext highlighter-rouge">0.35mA</code>), not too bad! Let’s measure the
voltage gain (with the signal source set to a peak amplitude of <code class="language-plaintext highlighter-rouge">1mV</code> and a <code class="language-plaintext highlighter-rouge">100K</code>
\(\Omega\) load attached):</p>

<p><img src="https://journal.lunar.sh/images/3/43.png" alt="enter image description here" width="500px" /></p>

<p>Our output across our load is seen reaching an amplitude of <code class="language-plaintext highlighter-rouge">70mV</code> and so we have
a voltage gain of <code class="language-plaintext highlighter-rouge">~70</code>.</p>

<h1 id="ltspice">LTSpice</h1>

<p>You can download <code class="language-plaintext highlighter-rouge">LTSpice</code> from
<a href="https://www.analog.com/en/design-center/design-tools-and-calculators/ltspice-simulator.html">https://www.analog.com/en/design-center/design-tools-and-calculators/ltspice-simulator.html</a></p>

<h1 id="signature">Signature</h1>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="rouge-code"><pre>+---------------------------------------+
|     .-.       .-.       .-.           |
|    /   \     /   \     /   \     +    |
|         \   /     \   /     \   /     |
|          "_"       "_"       "_"      |
|                                       |
|  _   _   _ _  _   _   ___   ___ _  _  |
| | | | | | | \| | /_\ | _ \ / __| || | |
| | |_| |_| | .` |/ _ \|   /_\__ \ __ | |
| |____\___/|_|\_/_/ \_\_|_(_)___/_||_| |
|                                       |
|                                       |
| Lunar RF Labs                         |
| Email: root@lunar.sh                  |
|                                       |
| Research Laboratories                 |
| OpenAlias (BTC, XMR): lunar.sh        |
| Copyright (C) 2022-2024               |
+---------------------------------------+
</pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name>Dylan Müller</name></author><summary type="html"><![CDATA[BJTs are important electronic devices that find use in a wide range of applications. Learn how to design circuits with them.]]></summary></entry></feed>