-
Notifications
You must be signed in to change notification settings - Fork 1
/
windows-basics.html
12 lines (10 loc) · 10.4 KB
/
windows-basics.html
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<title>Windows Basics</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="inner-content"><header class="page-header"><h1 class="page-title">Windows Basics</h1></header><div class="page-content"><p>This is a very brief article about some facts that should be common knowledge to Windows developers, but that Linux developers might not know.</p><h2>Win32 API</h2><p>The main <span style="color: #00ccff;">API</span> of Windows is provided through several <span style="color: #00ccff;">DLL</span>s (<span style="color: #00ccff;">D</span>ynamic <span style="color: #00ccff;">L</span>ink<span style="color: #00ccff;"> L</span>ibraries). An application can import functions from those <span style="color: #00ccff;">DLL</span> and call them. This way, the internal <span style="color: #00ccff;">API</span>s of the <span style="color: #00ccff;">Kernel</span> can change from a version to the next without compromising the portability of normal <span style="color: #00ccff;">user mode</span> applications.</p><h2>PE file format</h2><p><span style="color: #00ccff;">Executables</span> and <span style="color: #00ccff;">DLL</span>s are <span style="color: #00ccff;">PE</span> (<span style="color: #00ccff;">P</span>ortable <span style="color: #00ccff;">E</span>xecutable) files. Each <span style="color: #00ccff;">PE</span> includes an <span style="color: #00ccff;">import</span> and an <span style="color: #00ccff;">export table</span>. The <span style="color: #00ccff;">import table</span> specifies the functions to import and in which files they are located. The <span style="color: #00ccff;">export table</span> specifies the <span style="color: #00ccff;">exported functions</span>, i.e. the functions that can be imported by other <span style="color: #00ccff;">PE</span> files.</p><p><span style="color: #00ccff;">PE</span> files are composed of various <span style="color: #00ccff;">sections</span> (for code, data, etc…). The <span style="color: #00ff00;">.reloc</span> section contains information to relocate the <span style="color: #00ccff;">executable</span> or <span style="color: #00ccff;">DLL</span> in memory. While some addresses in code are relative (like for the relative jmps), many are absolute and depends on where the <span style="color: #00ccff;">module</span> is loaded in memory.</p><p>The<span style="color: #00ccff;"> Windows loader</span> searches for <span style="color: #00ccff;">DLL</span>s starting with the current <span style="color: #00ccff;">working directory</span>, so it is possible to distribute an application with a <span style="color: #00ccff;">DLL</span> different from the one in the system root (<span style="color: #00ff00;">\windows\system32</span>). This versioning issue is called <span style="color: #00ccff;">DLL-hell</span> by some people.</p><p>One important concept is that of a <span style="color: #00ccff;">RVA</span> (<span style="color: #00ccff;">R</span>elative <span style="color: #00ccff;">V</span>irtual <span style="color: #00ccff;">A</span>ddress). <span style="color: #00ccff;">PE</span> files use <span style="color: #00ccff;">RVA</span>s to specify the position of elements relative the <span style="color: #00ccff;">base address</span> of the <span style="color: #00ccff;">module</span>. In other words, if a <span style="color: #00ccff;">module</span> is loaded at an address <span style="color: #00ff00;">B</span> and an element has an <span style="color: #00ccff;">RVA</span> <span style="color: #00ff00;">X</span>, then the element’s absolute address in memory is simply <span style="color: #00ff00;">B+X</span>.</p><h2>Threading</h2><p>If you’re used to Windows, there’s nothing strange about the concept of <span style="color: #00ccff;">threads</span>, but if you come form Linux, keep in mind that Windows gives <span style="color: #00ccff;">CPU-time slices</span> to <span style="color: #00ccff;">threads</span> rather than to <span style="color: #00ccff;">processes</span> like Linux. Moreover, there is no <span style="color: #00ff00;">fork()</span> function. You can create new <span style="color: #00ccff;">processes</span> with <span style="color: #00ff00;">CreateProcess()</span> and new <span style="color: #00ccff;">threads</span> with <span style="color: #00ff00;">CreateThreads()</span>. <span style="color: #00ccff;">Threads</span> execute within the <span style="color: #00ccff;">address space</span> of the <span style="color: #00ccff;">process</span> they belong to, so they share memory.</p><p><span style="color: #00ccff;">Threads</span> also have limited support for non-shared memory through a mechanism called <span style="color: #00ccff;">TLS</span> (<span style="color: #00ccff;">T</span>hread <span style="color: #00ccff;">L</span>ocal <span style="color: #00ccff;">S</span>torage). Basically, the <span style="color: #00ccff;">TEB</span> of each thread contains a main <span style="color: #00ccff;">TLS</span> array of 64 DWORDS and an optional <span style="color: #00ccff;">TLS</span> array of maximum 1024 DWORDS which is allocated when the main <span style="color: #00ccff;">TLS</span> array runs out of available DWORDs. First, an index, corresponding to a position in one of the two arrays, must be allocated or reserved with <span style="color: #00ff00;">TlsAlloc()</span>, which returns the index allocated. Then, each <span style="color: #00ccff;">thread</span> can access the DWORD in one of its own two <span style="color: #00ccff;">TLS</span> arrays at the index allocated. The DWORD can be read with <span style="color: #00ff00;">TlsGetValue(index)</span> and written to with <span style="color: #00ff00;">TlsSetValue(index, newValue)</span>.<br> As an example, <span style="color: #00ff00;">TlsGetValue(7)</span> reads the DWORD at index 7 from the main <span style="color: #00ccff;">TLS</span> array in the <span style="color: #00ccff;">TEB</span> of the current <span style="color: #00ccff;">thread</span>.</p><p>Note that we could emulate this mechanism by using <span style="color: #00ff00;">GetCurrentThreadId()</span>, but it wouldn’t be as efficient.</p><h2>Tokens and Impersonation</h2><p><span style="color: #00ccff;">Tokens</span> are representations of <span style="color: #00ccff;">access rights</span>. <span style="color: #00ccff;">Tokens</span> are implemented as 32-bit integers, much like <span style="color: #00ccff;">file handles</span>. Each <span style="color: #00ccff;">process</span> maintains an internal structure which contains information about the <span style="color: #00ccff;">access rights</span> associated with the <span style="color: #00ccff;">tokens</span>.</p><p>There are two types of tokens: <span style="color: #00ccff;">primary tokens</span> and <span style="color: #00ccff;">secondary tokens</span>. Whenever a <span style="color: #00ccff;">process</span> is created, it is assigned a <span style="color: #00ccff;">primary token</span>. Each <span style="color: #00ccff;">thread</span> of that <span style="color: #00ccff;">process</span> can have the <span style="color: #00ccff;">token</span> of the <span style="color: #00ccff;">process</span> or a <span style="color: #00ccff;">secondary token</span> obtained from another <span style="color: #00ccff;">process</span> or the <span style="color: #00ff00;">LoginUser()</span> function which returns a new <span style="color: #00ccff;">token</span> if called with correct <span style="color: #00ccff;">credentials</span>.</p><p>To attach a <span style="color: #00ccff;">token</span> to the current <span style="color: #00ccff;">thread</span> you can use <span style="color: #00ff00;">SetThreadToken(newToken)</span> and remove it with <span style="color: #00ff00;">RevertToSelf()</span> which makes the <span style="color: #00ccff;">thread</span> revert to <span style="color: #00ccff;">primary token</span>.</p><p>Let’s say a user connects to a server in Windows and send <span style="color: #00ccff;">username</span> and <span style="color: #00ccff;">password</span>. The server, running as <span style="color: #00ccff;">SYSTEM</span>, will call <span style="color: #00ff00;">LogonUser()</span> with the provided <span style="color: #00ccff;">credentials</span> and if they are correct a new <span style="color: #00ccff;">token</span> is returned. Then the server creates a new <span style="color: #00ccff;">thread</span> and that <span style="color: #00ccff;">thread</span> calls <span style="color: #00ff00;">SetThreadToken(new_token)</span> where <span style="color: #00ff00;">new_token</span> is the <span style="color: #00ccff;">token</span> previously returned by <span style="color: #00ff00;">LogonUser()</span>. This way, the <span style="color: #00ccff;">thread</span> executes with the same privileges of the user. When the <span style="color: #00ccff;">thread</span> is finished serving the client, either it is destroyed, or it calls <span style="color: #00ff00;">revertToSelf()</span> and is added to the <span style="color: #00ccff;">pool of free threads</span>.<br> If you can take control of a server, you can revert to <span style="color: #00ccff;">SYSTEM</span> by calling <span style="color: #00ff00;">RevertToSelf()</span> or look for other <span style="color: #00ccff;">tokens</span> in memory and attach them to the current <span style="color: #00ccff;">thread</span> with<span style="color: #00ff00;"> SetThreadToken()</span>.</p><p>One thing to keep in mind is that <span style="color: #00ff00;">CreateProcess()</span> use the <span style="color: #00ccff;">primary token</span> as the <span style="color: #00ccff;">token</span> for the new <span style="color: #00ccff;">process</span>. This is a problem when the <span style="color: #00ccff;">thread</span> which calls <span style="color: #00ff00;">CreateProcess()</span> has a <span style="color: #00ccff;">secondary token</span> with more privileges than the <span style="color: #00ccff;">primary token</span>. In this case, the new <span style="color: #00ccff;">process</span> will have less privileges than the <span style="color: #00ccff;">thread</span> which created it.</p><p>The solution is to create a new <span style="color: #00ccff;">primary token</span> from the <span style="color: #00ccff;">secondary token</span> of the current <span style="color: #00ccff;">thread</span> by using <span style="color: #00ff00;">DuplicateTokenEx()</span>, and then to create the new <span style="color: #00ccff;">process</span> by calling <span style="color: #00ff00;">CreateProcessAsUser()</span> with the new <span style="color: #00ccff;">primary token</span>.</p> </div></div>
</body>
</html>