selinux簡介

来源:https://www.cnblogs.com/xiaoshiwang/archive/2020/03/01/12387549.html
-Advertisement-
Play Games

selinux概念 由美國國家安全局(NSA)和SCC聯合開發的,強制訪問控制的安全模塊。2000年以GPL開源,linux2.6內核後集成在內核里。 不啟用selinux時,訪問模式叫:DAC(discretionary access control)自由訪問控制 在DAC模式下的進程能夠訪問哪些 ...


selinux概念

由美國國家安全局(NSA)和SCC聯合開發的,強制訪問控制的安全模塊。2000年以GPL開源,linux2.6內核後集成在內核里。

不啟用selinux時,訪問模式叫:DAC(discretionary access control)自由訪問控制

在DAC模式下的進程能夠訪問哪些資源是由啟用這個進程的用戶身份決定的,這個用戶能訪問的,這個進程都可以訪問。

啟用selinux時,訪問模式叫:MAC(Mandatory access control)強制訪問控制

在MAC模式下的進程能夠訪問哪些資源是由selinux設定的。

selinux的工作類型

selinux的工作類型定義在/etc/selinux/config文件中

centos7:

# cat /etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

centos6:

# cat /etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted
  • targeted:保護常見的網路服務(預設工作類型)
  • minimum:只對選擇的服務保護

selinux安全上下文

  • 傳統linux,一切皆文件,由用戶,組,許可權控制訪問

  • 在selinux中,一切皆對象(object),由存放在inode的擴展屬性域的安全元素所訪問控制。

    查看inode的擴展屬性域的命令:ls -Zps -Z

    這些屬性起名叫標簽或context。

    ls:

    # ls -lZ
    -rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
    -rw-r--r--. root root system_u:object_r:admin_home_t:s0 initial-setup-ks.cfg
    -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 linux-3.10.67.tar.xz
    drwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 scripts

    ps:

    # ps auxZ
    LABEL                           USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    system_u:system_r:init_t:s0     root         1  0.0  0.1 193788  6904 ?        Ss   05:25   0:06 /usr/lib/systemd/systemd --swit
    system_u:system_r:kernel_t:s0   root         2  0.0  0.0      0     0 ?        S    05:25   0:00 [kthreadd]
    system_u:system_r:kernel_t:s0   root         3  0.0  0.0      0     0 ?        S    05:25   0:00 [ksoftirqd/0]
  • 所以文件,埠,進程都具備安全標簽:安全上下文(security context)

  • 安全上下位由5個元素組成:user:role:type:sensitivity:category

    • user:登錄系統的用戶類型
      • root:root用戶
      • user_u:普通用戶
      • system_u:系統用戶
      • unconfined_t:自由進程/文件。多數本地進程都屬於此。
    • role:定位文件,進程和用戶的用途。文件:object_r;進程和用戶:system_r
    • type:數據類型。最常用的屬性,target策略就是根據type的值,控制可以訪問/不可訪問哪些資源。但是有個問題,每個資源只有唯一的type,當有多個別的東西想訪問同一個資源的時候就麻煩了,就要修改type成public_content_t(只讀,不可以修改這個資源);public_content_rw_t(讀寫)
    • sensitivity:預設是s0
    • category:target工作類型下,不使用。
  • 標簽/context分實際的標簽和期望標簽

    • 實際標簽:使用ls -Z和ps -Z看到的標簽。

    • 期望標簽:安裝操作系統後,系統給的標簽。標簽是可以修改的,所以有期望標簽,修改了某個文件的標簽後,這個文件的期望標簽和實際標簽就不一樣了。

      查看文件,進程,埠的期望標簽:semanage fcontext -l

      # semanage fcontext -l | grep "/var/log/messages"
      /var/log/messages[^/]*                             all files          system_u:object_r:var_log_t:s0
      # ls -Z /var/log/messages
      -rw-------. root root system_u:object_r:var_log_t:s0   /var/log/messages

      期望標簽存放在:/etc/selinux/targeted/contexts/files/目錄

      # ls /etc/selinux/targeted/contexts/files/
      file_contexts           file_contexts.homedirs.bin  file_contexts.subs
      file_contexts.bin       file_contexts.local         file_contexts.subs_dist
      file_contexts.homedirs  file_contexts.local.bin     media

selinux策略

  • object:所以可以讀取的對象,包括文件,目錄,進程,埠
  • subject:進程
  • 當一個subject要訪問object時,selinux執行AVC(access vector cache)檢查,在AVC中,subject和object的許可權被緩存。
  • 安全策略:定義subject讀取object的規則資料庫,規則中記錄了哪個類型的(type)的subject使用哪個方法讀取哪一個object是允許的還是拒絕的,並且定義了哪種行為是允許或拒絕的。

啟用selinux

查看selinux是啟用還是禁用

# getenforce
Enforcing
[root@localhost ~]# cat /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

enforcing:啟用狀態

permissive:沒啟用,但是違反了selinux的規則,只出警告信息而已。

disabled:禁用狀態。

  • 臨時啟用:

    # setenforce 1
    # getenforce
    Enforcing
  • 臨時禁用:

    # setenforce 0
    # getenforce
    Permissive

    註意:使用命令setenforce,只能在Enforcing和Permissive間切換。不能從disabled狀態切換成Enforcing。

永久修改selinux啟用或禁用:修改文件/etc/selinux/config,重啟才生效。

禁用後(disabled而不是permissive)創建的文件就沒有標簽了,

而且【-rw-r--r--】後面沒有點,有點就說明有標簽。

# sestatus
SELinux status:                 disabled
# setenforce 1
setenforce: SELinux is disabled
# touch temp2
[root@localhost ~]# ls -Z temp2
-rw-r--r-- root root ?                                temp2

從disabled切換到enabled後,在看剛纔創建的temp2文件:

有點了,但是type是unlabeled_t

# getenforce
Enforcing
# ls -Z temp2
-rw-r--r--. root root system_u:object_r:unlabeled_t:s0 temp2

查看詳細狀態信息:

# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   permissive//當前是禁用的
Mode from config file:          enforcing//配置文件是啟用的
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Max kernel policy version:      31

定義的策略存放在:SELinuxfs mount /sys/fs/selinux

avc緩存在avc目錄。

# ls /sys/fs/selinux/
access    checkreqprot          context       disable           load    null                 policyvers      status
avc       class                 create        enforce           member  policy               reject_unknown  user
booleans  commit_pending_bools  deny_unknown  initial_contexts  mls     policy_capabilities  relabel

安全布爾值存放在:/sys/fs/selinux/booleans

# pwd
/sys/fs/selinux/booleans
[root@localhost booleans]# ll ftp*
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_anon_write
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_connect_all_unreserved
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_connect_db
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_full_access
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_use_cifs
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_use_fusefs
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_use_nfs
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_use_passive_mode

文件ftpd_anon_write里的內容是2個0。從文件名字可以看出來是ftp的匿名寫,值是0,說明不允許匿名寫。

# cat ftpd_anon_write
0 0

管理文件安全標簽

1,修改標簽中的type:chcon-t file

測試標簽中type的作用,/var/log/messages文件的標簽中的type是var_log_t。

手動使用logger命令,往它裡面寫東西,發現是可以寫進去的。

修改它的type成tmp_t,再用logger寫,發現寫不進去了。

# ll /var/log/messages -Z
-rw-------. root root system_u:object_r:var_log_t:s0   /var/log/messages
# logger "test  sdf "
# tail -1 /var/log/messages
Feb 29 18:33:32 localhost root: test  sdf
# chcon -t tmp_t /var/log/messages
# ll -Z /var/log/messages
-rw-------. root root system_u:object_r:tmp_t:s0       /var/log/messages
# logger "test  2222sdf "
# grep "test  2222sdf " /var/log/messages

根據某個文件的標簽,修改:chcon --reference f1 f2

把文件f2的標簽修改成和文件f1完全一樣。

# ll -Z /tmp/website/
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 aa
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html
# chcon --reference /tmp/website/index.html /tmp/website/aa
# ll -Z /tmp/website/
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 aa
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html

選項-R:遞歸修改目錄所有的文件

# ls /tmp/website/d1
11  22
# ll /tmp/website/d1/11 -Z
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /tmp/website/d1/11
# ll /tmp/website/d1/22 -Z
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /tmp/website/d1/22
# ll /tmp/website/d1/ -Zd
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /tmp/website/d1/
# chcon -R --reference /var/www/html/ /tmp/website/d1/
# ll /tmp/website/d1/ -Zd
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /tmp/website/d1/
# ll /tmp/website/d1/ -Z
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 11
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 22

2,cp命令和mv命令多標簽的影響。

cp命令type會改變。

# ll -Z /var/log/messages
-rw-------. root root system_u:object_r:var_log_t:s0   /var/log/messages
# cp /var/log/messages /root/
# ll -Z messages
-rw-------. root root unconfined_u:object_r:admin_home_t:s0 messages

mv命令不改變type

# mv messages /tmp/
# ll /tmp/messages  -Z
-rw-------. root root unconfined_u:object_r:admin_home_t:s0 /tmp/messages

3,修改回原來的type,但是忘了原來的type是啥了怎麼辦,去看期望(原始)策略是啥。

# semanage fcontext -l | grep "/var/log/message"
/var/log/messages[^/]*       all files       system_u:object_r:var_log_t:s0

還有一種更簡單的方法:restorecon

# chcon -t tmp_t /var/log/messages
# ll -Z /var/log/messages
-rw-------. root root system_u:object_r:tmp_t:s0       /var/log/messages
# restorecon /var/log/messages
# ll -Z /var/log/messages
-rw-------. root root system_u:object_r:var_log_t:s0   /var/log/messages

把/var/log/messages回覆成原來的標簽後,有可能還log還是寫不進去,這時就要重啟服務了。systemctl rsyslog restart

4,修改httpd的預設根目錄,導致selinux標簽不對,網頁文件無法訪問。

  • 修改httpd的配置文件/etc/httpd/conf/httpd.conf,把服務的目錄修改成/tmp/website/

    # ll -Z /tmp/website/ -d
    drwxr-xr-x. root root unconfined_u:object_r:user_tmp_t:s0 /tmp/website/

    type是user_tmp_t

  • 在/tmp/website/建立index.html文件

    # ll -Z /tmp/website/
    -rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 index.html

    type是user_tmp_t

  • 啟動httpd

  • 在瀏覽器訪問index.html

  • 結果是訪問不到

原因:/tmp/website/index.html的標簽的type不符合selinux對httpd的要求,所以httpd進程無法訪問它。

httpd能夠訪問的標簽是:httpd_sys_content_t。

而/tmp/website/index.html文件的type是user_tmp_t,所以httpd不可以訪問它,被selinux給擋住了。

# ll -Zd /var/www/
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/

解決辦法:

1,安裝桌面小程式,能夠把selinux相關的信息顯示出來。(不安裝也無所謂)

2,添加/tmp/website/目錄的期望(預設)策略,到selinux。

添加選項:-a

指明type:-t

/tmp/website(/.*)?:正則表達式/tmp/website目錄自身和目錄下的所有文件的意思。

# semanage fcontext -a -t httpd_sys_content_t "/tmp/website(/.*)?"
# semanage fcontext -l | grep "/tmp/website"
tmp/website(/.*)?                                  all files          system_u:object_r:httpd_sys_content_t:s0

3,由於/tmp/website/有了期望策略,所以恢復/tmp/website/的標簽成,預設標簽。

選項-R:遞歸修改目錄下的所有文件。

# restorecon -R /tmp/website/
# ll -Zd /tmp/website/
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /tmp/website/
# ll -Z /tmp/website/
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html

4,重啟httpd

5,當不想讓/tmp/website/是httpd的根目錄了,刪除它在selinux里的期望策略

刪除選項:-d

# semanage fcontext -d -t httpd_sys_content_t "/tmp/website(/.*)?"

管理埠標簽

1,查看埠期望(預設)策略:

http協議的埠的期望(預設)策略:80, 81, 443, 488, 8008, 8009, 8443, 9000是可以使用的。

所以不能把其他的埠用於http服務。

# semanage port -l
SELinux Port Type              Proto    Port Number

afs3_callback_port_t           tcp      7001
afs3_callback_port_t           udp      7001
# semanage port -l | grep http
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000

2,添加埠到預設策略

選項-a:添加

選項-t:指定type

選項-p:指定傳輸層的協議(tcp或udp)類型

# semanage port -a -t http_port_t -p tcp 9932
[root@localhost ~]# semanage port -l | grep "^http_port_t"
http_port_t          tcp      9932, 80, 81, 443, 488, 8008, 8009, 8443, 9000

3,從預設策略里刪除埠

# semanage port -d -t http_port_t -p tcp 9932
# semanage port -l | grep "^http_port_t"
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000

4,把埠策略里的某個埠,移動到另一個策略

讓9000埠也能用於ssh服務。

# semanage port -l | grep "^http_port_t"
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
# semanage port -m -t ssh_port_t -p tcp 9000
# semanage port -l | grep "^ssh_port_t"
ssh_port_t                     tcp      9000, 22
# semanage port -l | grep "^http_port_t"
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443

管理selinux布爾值開關

布爾值的作用:細化控制某個服務里的某個小功能是否可以使用。

1,查看布爾值

State:是當前的狀態(記憶體中的)

Default:是預設值(本地磁碟存儲的)

# semanage boolean -l
SELinux boolean                State  Default Description

privoxy_connect_any            (on   ,   on)  Allow privoxy to connect any
smartmon_3ware                 (off  ,  off)  Allow smartmon to 3ware

比如:

httpd_enable_cgi:控制httpd的cgi功能是否可用。

httpd_enable_homedirs:控制httpd是否可以訪問家目錄。

# semanage boolean -l | grep httpd_enable
httpd_enable_cgi               (on   ,   on)  Allow httpd to enable cgi
httpd_enable_homedirs          (off  ,  off)  Allow httpd to enable homedirs

另一種命令:getsebool

選項-a:查看全部布爾值

# getsebool -a | grep httpd_use
httpd_use_cifs --> off
httpd_use_fusefs --> off

2,修改布爾值:setsebool

只修改當前狀態(重啟後,恢覆成default):

# setsebool httpd_enable_homedirs=on
# semanage boolean -l | grep httpd_enable
httpd_enable_cgi               (on   ,   on)  Allow httpd to enable cgi
httpd_enable_homedirs          (on   ,  off)  Allow httpd to enable homedirs
httpd_enable_ftp_server        (off  ,  off)  Allow httpd to enable ftp server

既修改當前狀態,也修改default狀態:

# semanage boolean -l | grep httpd_enable
httpd_enable_homedirs          (off  ,  off)  Allow httpd to enable homedirs
# setsebool -P httpd_enable_homedirs=on
# semanage boolean -l | grep httpd_enable
httpd_enable_homedirs          (on   ,   on)  Allow httpd to enable homedirs

3,查看都修改過哪些布爾值

# semanage boolean -l -C
SELinux boolean                State  Default Description

httpd_enable_homedirs          (on   ,   on)  Allow httpd to enable homedirs

管理日誌

日誌工具: yum install -y setroubleshoot。有圖形界面。

使用下麵命令啟動圖形界面:

# sealert

1,查看由selinux的限制導致的服務不好用的日誌,日誌文件:/var/log/message

由selinux的限制導致的服務不好用的日誌的特點是有:setroubleshoot字樣,並告訴使用sealert命令去查看詳細的日誌。選項-l後面的串是這條日誌的標識。

Mar  1 00:04:05 localhost python: SELinux is preventing in 。。。。。。。。
sealert -l 0d882054-5ff7-4693-bf09-7b02f763df6c

使用sealert查看:

# sealert -l 0d882054-5ff7-4693-bf09-7b02f763df6c

使用sealert輸出的日誌是保存在文件: /var/log/audit/audit.log

2,整理/var/log/audit/audit.log文件,輸出可讀的格式

# sealert -a /var/log/audit/audit.log

查看selinux幫助

安裝selinux幫助文檔:

# yum install selinux-policy-doc

查看與selinux相關的幫助文檔有哪些:

# man -k _selinux

如果沒有顯示出來,說明沒有更新man的資料庫,使用下麵的命令更新:

  • centos6:makewhatis
  • centos7:mandb

查看與ftp相關的selinux幫助:

# man 8 ftpd_selinux

c/c++ 學習互助QQ群:877684253

本人微信:xiaoshitou5854


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • A finally block does not always xecute. The code in the try block could go into an infinite loop, the exception could rigger a “fail fast” (which take ...
  • 項目需要(或者前後端分離的需要),前端我使用了用戶控制項庫,由後端用代碼載入和控制。 然而用戶控制項庫沒法指定資源字典,於是在用戶控制項的xaml文件裡面手工添加了資源字典 設計階段方便了,生成dll,被主程式調用的時候,就報錯了,說沒有該資源文件(d1.xaml),研究Pack Url後明白,可以有兩種 ...
  • C#中實現文件拖放打開的方法 設置Form屬性 AllowDrop = True; 在Form事件中 private void Form1_DragDrop(object sender, DragEventArgs e) { string localFilePath = ((System.Array ...
  • 修改註冊表,雙擊文件直接打開 string strProject = "Exec"; string p_FileTypeName =".cdb";//文件尾碼 string fileName = System.Windows.Forms.Application.ExecutablePath;// 獲 ...
  • 作者: 魔法軟糖 日期: 2020-02-27 引言 ************************************* .ini 文件是Initialization File的縮寫,即配置文件 。是windows的系統配置文件所採用的存儲格式。 它具有方便易用的特點,和註冊表的鍵值有著類似 ...
  • 最近開始試著玩Unity3D,要為場景中的物體編輯腳本。Unity3D推薦的腳本語言是C#,在Unity打開C#就會使用Visual Studio來進行編輯。 啟動Visual Studio之後註意到,Unity類和方法名都沒有代碼補全,而且Unity似乎也編譯不過: 在網上找了一圈,發現並沒有人遇 ...
  • 在 C 中 Object 是所有類的基類,所有的結構和類都直接或間接的派生自它。前面這段話可以說所有的 C 開發人員都知道,但是我相信其中有一部分程式員並不清楚甚至不知道我們常用的 ToString 、 Equals 和 GetHashCode 虛方法都來自於 Object 類,並且我們可以對它們進 ...
  • 前言 今天這篇博客是接我的上一篇博客 https://www.cnblogs.com/y-yp/p/12191258.html,繼續介紹一下MMF在Linux上的用法 ps:本來本地調試完case,想放到伺服器上跑跑看,結果竟然報"PlatformNotSupportedException",然後仔 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...