This demo is intended to present a weakness of PICFI as overcome by LPCFI. Instructions to run the demo are provided below.
LPCFI is implemented naively with a basic hash table serving as the fp-table. PICFI is not implemented but simulated. If a function address has been activated, the PICFI simulation regards such function as a legal target for any indirect call. This is more coarse than PICFI, but irrelevant for this demo.
The C code from the poster is available in demo.c
.
- Unix-like system
- C compiler (at
cc
) ar
to create a static library- Python 2
- This may be installed as
python2
orpython
; this document will assume it is installed aspython2
.
- This may be installed as
Simply run the build.sh
script:
sh buid.sh
-
Build the demo binaries -
demo-lpcfi
anddemo-picfi
- according to the above build instructions. -
In a shell, run:
python2 payload.py | ./demo-picfi
-
The addresses of some functions will appear (attacking ASLR is orthogonal to our purposes).
A prompt will appear asking for the desired value of
fp
whenfoo
is called with argumentn = 1
. Enter the value ofg
as it appears without the leading '0x'. -
Press enter.
-
A second prompt will appear asking for the desired value of
fp
whenfoo
is called with argumentn = 0
. Enter the value ofg
again as before. -
Notice that PICFI allows
g
to be called during the secondfoo
call despite that the only legal target at that point ish
. -
Repeat steps 3 - 5 after running
python2 payload.py | ./demo-lpcfi
- Notice that LPCFI prevents
g
from being called during the secondfoo
call.
Other combinations may be input into the payload.
The extended demo contains a vulnerability whereby an attacker may
modify the value of a function pointer whose value directly depends
upon the password entered by the user. When an incorrect password is
input, op
should be set to the value of nopriv
and then called, and
when the correct password ("secret") is input, op
should be set to the
value of priv
and then called. This loops until "finish" is input as the
password.
Observe the payload in payload.py
- it,
- on the first iteration, inputs the incorrect password and sets
op
tonopriv
's value (as expected by the programmer) - on the second iteration, inputs the correct password and sets
op
topriv
's value (also as expected by the programmer) - on the third iteration, inputs the incorrect password but sets
op
topriv
's value (which is unexpected by the programmer) - finally, ends the demo by inputting "finish" as the password.
- Change to the extended demo directory.
cd extended-demo
-
Build the demo binaries -
extended-demo-lpcfi
andextended-demo-picfi
- according to the above build instructions. -
Run
python2 payload.py | ./extended-demo-picfi
-
The addresses of some functions will appear (attacking ASLR is orthogonal to our purposes).
A prompt will appear asking for the value of
priv
Enter the value ofpriv
as it appears without the leading '0x'. -
Press enter.
-
Repeat steps 4 and 5 for
nopriv
. -
Notice that PICFI allows the user to call the privileged operation on the third iteration since the privileged function has been activated.
-
Repeat steps 4 - 6 after running
python2 payload.py | ./extended-demo-lpcfi
- Notice that LPCFI prevents
op
from being called during the third iteration since it carries an illegal value unexpected by the programmer.
The payload may be modified for other combinations.