基于rpc的攻击,rpc 计算机网络

RPC在内网的攻击面

1、前言

最近研究RPC在内网中的一些攻击面,主要是以红队视角来看,使用RPC协议有时候Bypass EDR等设备会有较好的效果,那么什么是RPC呢,RPC 代表“远程过程调用”,它不是 Windows 特定的概念。RPC 的第一个实现是在80年代在UNIX系统上实现的。这允许机器在网络上相互通信,它甚至被“用作网络文件系统(NFS)的基础”,其实简单的说就是它允许请求另一台计算机上的服务,本节内容主要是依靠microsoft官方文档进行学习(***/zh-cn/windows/win32/rpc/rpc-start-page)。

2、RPC结构相关概念

1、首先我们要理解RPC是如何进行通信的首先需要知道几个概念IDL文件,UUID,ACF文件

IDL文件:为了统一客户端与服务端不同平台处理不同的实现,于是有了IDL语言。IDL文件由一个或多个接口定义组成,每一个接口定义都有一个接口头和一个接口体,接口头包含了使用此接口的信息(UUID和接口版本),接口体包含了接口函数的原型相关细节查看***/zh-cn/windows/win32/rpc/the-interface-definition-language-idl-file。

UUID:通常为一个16长度的标识符,具有唯一性,在Rpc通信模型中,UUID 提供对接口、管理器入口点向量或客户端对象等对象的唯一指定。

ACF:(ACF) 的应用程序配置文件有两个部分: 接口标头,类似于 IDL 文件中的接口标头,以及一个 正文,其中包含适用于 IDL 文件的接口正文中定义的类型和函数的配置属性***/zh-cn/windows/win32/rpc/the-application-configuration-file-acf-。

2、调用过程

RpcStringBindingCompose:需要先创建一个绑定句柄字符串。***/zh-cn/windows/win32/api/rpcdce/nf-rpcdce-rpcstringbindingcompose。

RpcBindingFromStringBinding:通过绑定句柄字符串返回绑定句柄***/zh-cn/windows/win32/api/rpcdce/nf-rpcdce-rpcstringbindingcompose。

3、存根分配和释放内存

在编写RPC调用的时候,必须将函数MIDL_user_allocate和MIDL_user_free在项目的中定义。

RPC在内网的攻击面

3、相关攻击面

1、IOXID Resolver探测内网多网卡主机

我们发送一个IOXID的传输包,这个发送方式有很多种,我这里用的K8师傅的工具,用Wireshark抓包。

RPC在内网的攻击面

上图中TCP的三个包就不用看了,就是很常见的TCP的三次握手,后四个包中可以如图看,主要关注的是最后一个包,前三个都是固定的,就是交互中用来协商版本之类的参数。

1、先来构造第一个数据包,由于这个包是固定的可以直接Copy Wireshark中的,如下图

05000b03100000004800000001000000b810b810000000000100000000000100c4fefc9960521b10bbcb00aa0021347a00000000045d888aeb1cc9119fe808002b10486002000000

RPC在内网的攻击面

2、后续第二个是接受的数据包,直接将第三个包复制就可以

050000031000000018000000010000000000000000000500

3、主要就是看我们如何剖析最后一个包,将他接收过来并且进行一个分割输出,首先我们是想要枚举他的多网卡信息,和主机信息。我们对数据包进行一个分割。是从/0x07/0x00/进行分割。

RPC在内网的攻击面

结束的是在0x09/0x00/0xff这一块结束的,把我们接受的数据进行一个分割。

RPC在内网的攻击面

相关代码:***/M0nster3/RpcsDemo/blob/main/OXIDINterka_network_card/OXID.go

效果图

RPC在内网的攻击面

2、RPC SMB

RPC还可以通过不同的协议进行一个访问,例如通过SMB协议传输的RPC服务就可以通过管道进行访问,加入在做项目的时候又有个域凭证就可以进行一写RPC借口的一个调用,比较好用的一个工具是rpcclient,它是执行客户端 MS-RPC 功能的工具。
相关命令的一些总结我发在了***/M0nster3/RpcsDemo/blob/main/RPC%20over%20SMB/MS-RPC.md中,大家有需要可以去提取。

3、MS-SAMR的那些事

该协议支持包含用户和组的帐户存储或目录的管理功能,简单来说就是该协议主要是对Windows用户以及用户组的一些相应操作,例如添加用户,用户组等操作。官方参考:***/zh-cn/openspecs/windows_protocols/ms-samr/4df07fab-1bbc-452f-8e92-7853a3c7e380

1)添加本地用户

调用的API SamrCreateUser2InDomain()可以创建一个用户.

long SamrCreateUser2InDomain( [in] SAMPR_HANDLE DomainHandle, [in] PRPC_UNICODE_STRING Name, [in] unsigned long AccountType, [in] unsigned long DesiredAccess, [out] SAMPR_HANDLE* UserHandle, [out] unsigned long* GrantedAccess, [out] unsigned long* RelativeId );

在创建用户的时候通过分档来看,不能直接创建到内置域(Builtin)中,需要先创建到账户域(账户)中,如下图。

关于内置域和账户域的相关内容可以参考官方链接:***/zh-cn/windows/win32/secmgmt/built-in-and-account-domains

其实简单来说就是,账户域内的用户只能访问该账户所在计算机的资源,而内置域中的账户可以访问域的资源。

RPC在内网的攻击面

由于使用SamrCreateUser2InDomain创建的账户存在禁用标识位,我们先需要为它Set一个属性,来清除禁用标识位。然后才可以将其加入到所在的内置域中。

使用SamrSetInformationUser() 这个API为它设置。

long SamrSetInformationUser( [in] SAMPR_HANDLE UserHandle, [in] USER_INFORMATION_CLASS UserInformationClass, [in, switch_is(UserInformationClass)] PSAMPR_USER_INFO_BUFFER Buffer );

编写脚本有两种方式一种是直接调用MS-SAMR协议去直接创建一个用户,微软官方给了IDL***/en-us/openspecs/windows_protocols/ms-samr/1cd138b9-cc1b-4706-b115-49e53189e32e,将其编译,然后构造,这种方式调用起来比较麻烦,另一种是使用神器mimikatz打包好的包,samlib来进行调用,调用的时候将前面的samr改成sam就可以.

参考微软给的官方例子:***/en-us/openspecs/windows_protocols/ms-samr/3d8e23d8-d9df-481f-83b3-9175f980294c

可以按照这个例子依次构造

RPC在内网的攻击面

首先先求出来账户域Account和内置域的Builts的SID为后续添加账户以及加入到内置域中做准备。

RPC在内网的攻击面

然后获取域对象的句柄,然后为域对象添加用户,并且清除禁用标识位,关键代码。

RPC在内网的攻击面

到这里创建用户的准备工作就结束了,接下来,就是将用户添加到组里面,用到SamAddMemberToAlias这个API***/en-us/openspecs/windows_protocols/ms-samr/9a5d2c35-e84b-4e59-b7b0-96c6fa0fc8d7

long SamrAddMemberToAlias( [in] SAMPR_HANDLE AliasHandle, [in] PRPC_SID MemberId );

相应的Demo:***/M0nster3/RpcsDemo/blob/main/MS-SAMR/AddUser/AddUser/main.c

RPC在内网的攻击面

2) Change Ntlm

调用的关键API在SamrChangePasswordUser() ***/en-us/openspecs/windows_protocols/ms-samr/9699d8ca-e1a4-433c-a8c3-d7bebeb01476,

当我们获取到了用户名,以及密码NTLMhash,则可以是用这个API将用户的密码修改了。

long SamrChangePasswordUser( [in] SAMPR_HANDLE UserHandle, [in] unsigned char LmPresent, [in, unique] PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm, [in, unique] PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm, [in] unsigned char NtPresent, [in, unique] PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt, [in, unique] PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt, [in] unsigned char NtCrossEncryptionPresent, [in, unique] PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm, [in] unsigned char LmCrossEncryptionPresent, [in, unique] PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt );

这这里遇到了一个坑,就是只用旧的Ntlm就行修改而不对LmCrossEncryptionPresent和NewLmEncryptedWithNewNt进行传参,则会输出一个C000017F的错误,如下图。

RPC在内网的攻击面RPC在内网的攻击面

我去查看一下这个错误发现是客户端使用当前密码LM hash作为加密密钥请求返回,不清楚为什么不能用当前的密码LM hash,就改了一个其他的LM hash,关键代码。

RPC在内网的攻击面

接下来就是编写POC,我在这里使用微软官方的提供的IDL进行编译 ***/en-us/openspecs/windows_protocols/ms-samr/1cd138b9-cc1b-4706-b115-49e53189e32e,提供了我们需要的所有包,在我们编译好,生成exe的时候会有很多错误,直接将其都注释就好。

根据RPC的调用过程首先需要进行RPC的绑定

RPC_STATUS RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR ProtSeq, RPC_WSTR NetworkAddr, RPC_WSTR Endpoint, RPC_WSTR Options, RPC_WSTR *StringBinding);

其中的ObjUuid可以直接在提供的IDL中找到,如下图,但是发现这个例子有没有这个都可以,最主要的必须定义一个命名管道端点 PIPEsamr。***/en-us/openspecs/windows_protocols/ms-wkst/13e9ee5d-4125-4492-bcc7-9a0061f2bbe7关键代码

RPC在内网的攻击面

绑定了之后接下来就是构造SamrChangePasswordUser,***/en-us/openspecs/windows_protocols/ms-samr/9699d8ca-e1a4-433c-a8c3-d7bebeb01476如果我们不熟悉MS-SAMR我们可以倒着堆整个调用流程。

long SamrChangePasswordUser( [in] SAMPR_HANDLE UserHandle, [in] unsigned char LmPresent, [in, unique] PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm, [in, unique] PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm, [in] unsigned char NtPresent, [in, unique] PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt, [in, unique] PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt, [in] unsigned char NtCrossEncryptionPresent, [in, unique] PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm, [in] unsigned char LmCrossEncryptionPresent, [in, unique] PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt );

根据上面的图,以及相关的官方文档,我们发现我们现在就需要传入一个UserHandle用户句柄,其他的就是我们需要输入的NT hash,以及我们需要修改的新的NT hash,那么这个UserHandle需要从哪里获取呢。这时候可以翻看官方文档。发现一个API SamrOpenUser()***/en-us/openspecs/windows_protocols/ms-samr/0aee1c31-ec40-4633-bb56-0cf8429093c0如下,可以为我们提供我们需要的Userhandle,

这个API意思就是通过RID来获取用户句柄。

long SamrOpenUser( [in] SAMPR_HANDLE DomainHandle, [in] unsigned long DesiredAccess, [in] unsigned long UserId, [out] SAMPR_HANDLE* UserHandle );

继续查看这个API需要什么参数,需要一个域的句柄,所需要的访问权限查看文档***/en-us/openspecs/windows_protocols/ms-samr/c0be3f43-bcf9-43ee-b027-3d02ab372c53,如下图,由于我们是要实现修改密码,所以我们需要一个指定修改用户密码的能力USER_CHANGE_PASSWORD,最后还需要一个RID。

RPC在内网的攻击面

通过上面的分析,我们现在好需要两个参数,一个参数是DomainHandle,另一个就是UserId.

继续翻看文档发现这样一个API SamrLookupNamesInDomain(),***/en-us/openspecs/windows_protocols/ms-samr/d91271c6-7b2e-4194-9927-8fabfa429f90如下

就是将我们输入的用户名转化为RID,输出一个RID号,到这里我们上面所需要的两个参数中的UserId就找到了。

这里需要的两个参数就是我们输入的用户名,还有和上面SamrOpenUser通向需要的的 DomainHandle。

long SamrLookupNamesInDomain( [in] SAMPR_HANDLE DomainHandle, [in, range(0,1000)] unsigned long Count, [in, size_is(1000), length_is(Count)] RPC_UNICODE_STRING Names[*], [out] PSAMPR_ULONG_ARRAY RelativeIds, [out] PSAMPR_ULONG_ARRAY Use );

我们继续找返现 SamrOpenDomain***/en-us/openspecs/windows_protocols/ms-samr/ba710c90-5b12-42f8-9e5a-d4aacc1329fa这个API,通过SID号可以输出我们需要的域对象句柄。

long SamrOpenDomain( [in] SAMPR_HANDLE ServerHandle, [in] unsigned long DesiredAccess, [in] PRPC_SID DomainId, [out] SAMPR_HANDLE* DomainHandle );

到这里SamrOpenUser这个API所需要的条件就找全了。

我们需要继续为SamrOpenDomain寻找它所需要输入的内容,服务器句柄,SID号

这一块可以使用SamrLookupDomainInSamServer来获取我们需要的SID.

这个需要一个内置域的名称,也就是上面上面添加本地用户中提到的获取内置域的名称就可以,这里填写“Builtin”以及一个服务器句柄。

long SamrLookupDomainInSamServer( [in] SAMPR_HANDLE ServerHandle, [in] PRPC_UNICODE_STRING Name, [out] PRPC_SID* DomainId );

获取服务器对象的句柄使用到的API SamrConnect5。***/en-us/openspecs/windows_protocols/ms-samr/c842a897-0a42-4ca5-a607-2afd05271dae

这个API 会返回服务器对象的句柄,需要我们填入我们的服务器,直接填写机器名称就可以。

long SamrConnect5( [in, unique, string] PSAMPR_SERVER_NAME ServerName, [in] unsigned long DesiredAccess, [in] unsigned long InVersion, [in] [switch_is(InVersion)] SAMPR_REVISION_INFO* InRevisionInfo, [out] unsigned long* OutVersion, [out, switch_is(*OutVersion)] SAMPR_REVISION_INFO* OutRevisionInfo, [out] SAMPR_HANDLE* ServerHandle );

总结一下:

1、我们首先利用 SamrConnect5 获取服务器句柄。

2、利用获取到的服务器句柄经过SamrLookupDomainInSamServer获取服务器SID,。

3、接着利用对一步中获取的服务器句柄以及第二步中的SID利用SamrOpenDomain获取域句柄

4、接下来利用获取到的域句柄利用SamrLookupNamesInDomain获取RID号

5、接着利用第四步中的RID以及第三步中的域句柄利用SamrOpenUser API获取用户句柄

6、最后利用用户句柄以及之前的NT hash和需要修改的Nt Hash调用SamrChangePasswordUser修改密码。

想要修改的Nt hash 可以使用 python2 。

import hashlib,binasciiprint binascii.hexlify(hashlib.new("md4", "123456".encode("utf-16le")).digest())

效果图:

RPC在内网的攻击面

完整的Demo:

***/M0nster3/RpcsDemo/blob/main/MS-SAMR/ChangeNTLM/ChangePass/main.c

4、MS-TSCH

[MS – TSCH]:任务计划程序服务远程协议,用于注册和配置任务以及查询远程计算机上运行的任务的状态。顾名思义就是利用这个API可以操纵计划任务。***/zh-cn/openspecs/windows_protocols/ms-tsch/d1058a28-7e02-4948-8b8d-4a347fa64931

直接来看相关API SchRpcRegisterTask() ***/zh-cn/openspecs/windows_protocols/ms-tsch/849c131a-64e4-46ef-b015-9d4c599c5167

直接向服务器注册一个任务,关键的两个参数一个是我们创建服务的路径,另一个就是定义计划任务的xml。

HRESULT SchRpcRegisterTask( [in, string, unique] const wchar_t* path, [in, string] const wchar_t* xml, [in] DWORD flags, [in, string, unique] const wchar_t* sddl, [in] DWORD logonType, [in] DWORD cCreds, [in, size_is(cCreds), unique] const TASK_USER_CRED* pCreds, [out, string] wchar_t** pActualPath, [out] PTASK_XML_ERROR_INFO* pErrorInfo );

奇怪的是我们在编写的时候总是提示我们缺少参数,如下图,我们缺少一个句柄,这个句柄就是我们写RPC时候的一个绑定句柄,这个Demo写起来就简单多了,不需要之前那么多要求,只要配置一个RPC绑定就可以了。

RPC在内网的攻击面

本来以为很简单直接写一个绑定就可以,没想到调用之前的绑定,发现总是失败,后来查找github别人的源码发现需要多一步验证,需要实现RpcBindingSetAuthInfoExA,真是吐了。

RPC_STATUS RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, unsigned long AuthnLevel, unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvc, RPC_SECURITY_QOS *SecurityQos);

关键代码

RPC在内网的攻击面

效果图:

RPC在内网的攻击面RPC在内网的攻击面

相关代码:

***/M0nster3/RpcsDemo/blob/main/MS-TSCH_DESK/RPCDESK/RPCDESK/main.c

5、MS-SCMR

[MS – SCMR]:服务控制管理器远程协议***/en-us/openspecs/windows_protocols/ms-scmr/705b624a-13de-43cc-b8a2-99573da3635f

指定服务控制管理器远程协议,用于远程管理服务控制管理器 (SCM),这是一个启用服务配置和服务程序控制的 RPC 服务器。其实就是一个管理服务的一个RPC协议。

需要调用ROpenSCManagerA、RCreateServiceA也可以创建服务,除了这个之外还可以查看很多文档,还有许多API来使用。

DWORD ROpenSCManagerA( [in, string, unique, range(0, SC_MAX_COMPUTER_NAME_LENGTH)] SVCCTL_HANDLEA lpMachineName, [in, string, unique, range(0, SC_MAX_NAME_LENGTH)] LPSTR lpDatabaseName, [in] DWORD dwDesiredAccess, [out] LPSC_RPC_HANDLE lpScHandle );
DWORD RCreateServiceA( [in] SC_RPC_HANDLE hSCManager, [in, string, range(0, SC_MAX_NAME_LENGTH)] LPSTR lpServiceName, [in, string, unique, range(0, SC_MAX_NAME_LENGTH)] LPSTR lpDisplayName, [in] DWORD dwDesiredAccess, [in] DWORD dwServiceType, [in] DWORD dwStartType, [in] DWORD dwErrorControl, [in, string, range(0, SC_MAX_PATH_LENGTH)] LPSTR lpBinaryPathName, [in, string, unique, range(0, SC_MAX_NAME_LENGTH)] LPSTR lpLoadOrderGroup, [in, out, unique] LPDWORD lpdwTagId, [in, unique, size_is(dwDependSize)] LPBYTE lpDependencies, [in, range(0, SC_MAX_DEPEND_SIZE)] DWORD dwDependSize, [in, string, unique, range(0, SC_MAX_ACCOUNT_NAME_LENGTH)] LPSTR lpServiceStartName, [in, unique, size_is(dwPwSize)] LPBYTE lpPassword, [in, range(0, SC_MAX_PWD_SIZE)] DWORD dwPwSize, [out] LPSC_RPC_HANDLE lpServiceHandle );

通过创建的服务是没有开启的,这个时候我们就需要一个开启的API RStartServiceA,准备好了所有的东西,就可以开始编写Demo。

相关Demo和之前的一样哪些搞就可以了,这里写几个注意的点。

1、当我们使用官方给的IDL编写的时候有很多重命名,我们直接注释就可以,还有一些我们代码中可能用不到的方法,但是由于是使用官方的IDL编译的,所以需要我们实现一下。

2、创建服务的时候只能直接将我们的EXE作为服务启动,因为不是所有程序都可以作为服务的方式运行,作为服务运行需要能返回运行情况等信息,所以有的程序添加后会,这里我提供一个方法,就是使用微软官方的程序srvany.exe

1)首先将srvany.exe添加到服务中并且启动。

​ 2)将我们要执行的内容路径放入到注册表中

reg add HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesServiceNameParameters /v AppDirectory /t REG_SZ /d "c:" /f

​ 3)然后将程序放入注册表

reg add HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesServiceNameParameters /v Application /t REG_SZ /d "c:xxx.exe" /freg add HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesServiceNameParameters /v AppParameters /t REG_SZ /d "如果程序需要参数则填在这里,如果不需要,清空这段文字或者整行" /f

效果图:

RPC在内网的攻击面

ng)

RPC在内网的攻击面

这里我们将我们的shellcode执行一下,添加注册表的时候需要将servicesname改为你添加任务的名字。

RPC在内网的攻击面RPC在内网的攻击面

而且这里还是system权限。

6、Seclogon Dump Lsass

这个是splinter_code 这个师傅发现的***/p/the-hidden-side-of-seclogon-part-2.html

它的原理主要是,不直接调用OpenProcess去打开进程对象,而是利用已经打开的Lsass进程句柄,从而绕过检测,然后利用RpcImpersonateClient尝试使用PID做一个调用者的伪造。

关键细节可以看这个师傅的博客说的很详细了:

效果图:

RPC在内网的攻击面

需要将我们的第一步-t 1的提取出来,不然直接使用-t 2解密之后会被杀软杀了。

(0)
上一篇 2023年3月28日 下午1:18
下一篇 2023年3月28日 下午1:22

相关推荐

  • 西洋参有哪些功效和作用(西洋参的功效和作用价格)

    西洋参,顾名思义就是西方的参,属于少有不上火的滋补品,主产于美国、加拿大,在我们大国东北也有栽培着。国产的西洋参药效完全是可替代进口, 国产也是不错,性价比高。 西洋参,又叫花旗参…

    2023年6月19日
    0
  • 用白醋洗脸有什么好处(用白醋洗头)

    坚持用白醋洗脸,到底有什么好处?今天可算明白了 美白 白醋美白的具体做法:一定要用温水,里面滴5-6滴白醋,不能太多。洗脸之前先洗手,这样会有效的避免将手上的细菌带到脸上。白醋美白…

    生活百科 2023年6月2日
    0
  • 经典文言文赏析盲子失坠(盲子失坠单字翻译)

    原文 有盲子道①涸溪,桥上失坠,两手攀楯②,兢兢③握固,自分④失手,必坠深渊矣。过者告曰:“毋⑤怖,第⑥放下即实地也。”盲子不信,握楯长号。久之,力惫,失手坠地,乃自哂⑦曰:“嘻!…

    2023年3月15日
    0
  • 去年端午节的葫芦还能挂吗

    端午节是中国传统节日之一,也是重要的民俗文化节日。在这个节日里,人们会包粽子、赛龙舟、挂艾叶和挂葫芦。葫芦是端午节必不可少的道具之一,但是,去年端午节的葫芦还能挂吗? 首先,我们需…

    生活百科 2023年9月13日
    0
  • 螃蟹怎么炒好吃

    本文目录 1.准备材料 2.煮螃蟹 3.炒螃蟹 4.小贴士 螃蟹是夏季的一道美食,但是很多人都不知道如何烹调才能让螃蟹更加美味可口。下面是一些制作螃蟹的技巧,希望对你有所帮助。 准…

    生活百科 2023年7月9日
    0
  • 春节小兔子

    虎去兔来,在庆祝春节的各个文创产品中,兔元素渐入高潮。跟往年相比,今年本身带有萌宠特质的生肖兔产品更加丰富多彩。义乌兔元素的小商品供不应求,远销全球;各个酒厂纷纷推出“生肖酒”,主…

    生活百科 2023年2月14日
    0
  • 无糖的饮料真的不含糖吗实验报告

    【编者按】近年来,随着“无糖”概念的产品兴起,“无糖”食品、饮料以及其宣传的“健康生活”正逐渐取得消费者的认可,不少食品、饮料也以“0糖0脂0能量”作为卖点。那么,为何要减少糖的摄…

    生活百科 2023年5月5日
    0
  • 汉族中秋节有没有上坟或烧纸的习俗

    中秋节是我国传统的重要节日之一,汉族在这一天有着丰富多彩的庆祝活动。但是,关于是否有上坟或烧纸的习俗,却存在着不同的看法和做法。 在一些地区,汉族家庭会在中秋节期间前往祖坟扫墓,祭…

    生活百科 2023年7月31日
    0
  • 大年三十晚上为什么吃饺子

    中国传统文化中,春节是最重要的节日之一。春节的前一天,即大年三十晚上,人们在家庭团聚的同时,也会在饭桌上摆上一道道美食,其中最重要的就是饺子。 那么,为什么大年三十晚上要吃饺子呢?…

    生活百科 2023年6月18日
    0
  • 唇疱疹好后嘴巴反复蜕皮怎么回事

    唇疱疹是一种常见的病毒感染,通常会在唇部和口周出现疱疹和疼痛。虽然唇疱疹通常会自行愈合,但某些人在疱疹好转后会出现嘴巴反复蜕皮的情况。 这是因为唇疱疹病毒会感染口唇和嘴角的皮肤,导…

    生活百科 2023年7月7日
    0

发表评论

登录后才能评论