Original idea: https://gist.github.com/sampritipanda/3ad8e88f93dd97e93f070a94a791bff6
$ ./extract.sh
$ ./run.sh
$ ./exploit
There is a kernel module that you can use through ioctl. After reversing the module we came up with the following structures:
struct string {
char *str;
struct len_pid *info;
}
struct len_pid {
int64_t pad; // set always to 0
int32_t pid; // the pid of the process that add the following structure
int32_t len; // the length of str
}
struct string *storages[16]; // global
And in userspace we communicate with:
struct request_t {
char *buffer; // this will be saved in string->str
char *garbage;
}
Commands:
- ADD -> Add a
string
to storages - FREE -> Free a
string
from storages - READ -> The module with the READ operation will put inside the
request.garbage
address 8 bytes of 0, the pid value and the len value
I tried at first some heap exploitation stuff but it didn't work.
The easier thing to do is to use the READ operation to write inside the address of
modprobe_path
a different string (which is the name of the program to be executed
when a binary format file is not recognized). To write the value you use
the pid of the process. From my understanding this works because the module uses
copy_user_generic_unrolled
instead of copy_to_user
to copy the value.
I tried to set instead of /tmp/a
~/aa
, but modprobe_path
doesn't seem to understand
the ~
(in this way it could be possible to write two consecutive write without looping
through all the possible pid three times)
At the moment the exploit works without KASLR
.