例题一(32位):
一:gdb调试找所需的地址:
1:libc地址
2: 找libc基地址
然后用libc地址减去libc基地址得出偏移。
不论程序中的函数地址如何变化,之间的偏移是不会变的。exp中泄露的libc地址减去这个偏移就是libcbase的地址。
二:复写got表
查看printf函数地址和system地址有几位不一样。
printf_got 与printf_got+2:
也就是说先%6$n改写后俩字节,然后%7$n再改写printf_got+2的后俩字节,最后拼在一起就是改写成system的地址了。
先改写printf_got的后俩字节:
修改成功。
再来修改高位两字节:
之后就能拿到shell。
例题二(64位):
main函数:
方法一:劫持malloc_hook/free hook
修改malloc_hook为onegadget 。
gdb调试:
再找到栈基地址,libc-栈基地址得到偏移,在利用libcbase+libc.symbols['__malloc_hook']即可得到malloc_hookf真实地址 。
方法二:劫持返回地址
在printf处下断点,c之后输入程序所需的 "Hey,siri!",再c运行,再输入”Remind me to“,再查看栈:
栈顶存储的是printf函数的返回地址,printf执行完后会返回到该地址,那么我们可以将该地址覆盖位onegadget,
exp
把发送大量信息触发malloc_hook的给注释掉,劫持返回地址不用触发malloc_hook,rip的地址由gdb调试得到,
随便泄露一个栈地址,然后gdb中对应的栈减去rsp得到偏移,再利用泄露的栈地址减去偏移即为栈顶地址。
例题三:
main函数
printf("%*d",5,10)就是*取5当作宽度输出10,printf("%.*s",3,'abcdef')是.*取3当作要输出对象的前几个字符。
gdb调试程序:
调试payload:
第一个payload:
在fprintf处下断点,c运行到此处。
改写栈链指向第一个随机数的地址
计算相对于输入的格式化字符串的偏移位置,由于是aaaa 第二个参数,fmtarg算出的要减去1。
改写成功
第二个payload:
看下第一个随机数地址的偏移:
栈拉长一点
getshell。
例题四:
main函数:
只有一个printf,需要多次运行。如何多次运行?
可以看出main函数不是第一个执行的函数,main函数执行完退出程序时会执行fini_array内的函数。 ctrl+s查看
如果把这个do_global...............函数改为main函数,那么又可以运行一次main函数。不是无限循环main,gdb源码级调试看原因:
先看下源码级调试的准备工作
先下载源码,编辑gdbinit文件。
加入源码目录后gdb调试执行到这个函数的时候就能看见对应的源码。
开始调试:
可以看到_dl_fini函数会调用fini_array。
####################################################
第一个题快速生成payload
int一次性写入四字节,short 一次性写入2字节,bit一次性写入一字节。工具有局限性,有的题对payload构造有要求,比如对齐程序的字符串。
Comments | NOTHING