ÜberWall

UWvbiosdump

/* $Id: UWvbiosdump.c,v 1.1 2012/07/06 00:00:09 khorben Exp $ */
/* Copyright (c) 2012 khorben of UberWall <khorben@uberwall.org> */
/* This file is part of UWvbiosdump
* Video BIOS dumper
* UberWall security team \../. .\../ */
/* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
/* UWvbiosdump */
/* private */
/* prototypes */
static int _UWvbiosdump(char const * filename);
static int _error(char const * message, int ret);
static int _usage(void);
/* functions */
/* UWvbiosdump */
static int _UWvbiosdump(char const * filename)
{
int ret = 0;
FILE * fp;
int fd;
size_t base = 0xc0000;
size_t size;
char * p;
/* open /dev/mem */
fprintf(stderr, "[*] %s\n", "Opening /dev/mem");
if((fd = open("/dev/mem", O_RDONLY)) < 0)
return _error("/dev/mem", 1);
/* obtain the size */
fprintf(stderr, "[*] %s\n", "Mapping /dev/mem in memory");
if((p = mmap(0, 32, PROT_READ, MAP_SHARED, fd, base)) == MAP_FAILED)
{
close(fd);
return _error("mmap", 1);
}
size = p[2] * 512;
if(size == 0) /* XXX also bailout if it is too big */
{
/* the size is invalid */
munmap(p, 32);
close(fd);
fprintf(stderr, "[!] %s\n", "The Video BIOS is not available");
return 1;
}
fprintf(stderr, "[+] %s%lu\n", "Mapped, size is ", size);
/* remap to the complete size */
fprintf(stderr, "[*] %s\n", "Remapping /dev/mem with the new size");
if((p = mremap(p, 32, p, size, 0)) == MAP_FAILED)
{
close(fd);
return _error("mmap", 1);
}
fprintf(stderr, "[+] %s\n", "Remapped /dev/mem");
/* dump the Video BIOS */
fprintf(stderr, "[*] %s\n", "Dumping the Video BIOS");
if(filename == NULL)
fp = stdout;
else if((fp = fopen(filename, "wb")) == NULL)
{
close(fd);
return _error(filename, 1);
}
if(fwrite(p, size, 1, fp) != 1)
ret = _error((filename != NULL) ? filename : "stdout", 1);
else
fprintf(stderr, "[+] %s\n", "Dumped the Video BIOS");
/* cleanup */
if(filename != NULL)
fclose(fp);
if(munmap(p, size) != 0)
ret = _error("/dev/mem", 1);
close(fd);
return ret;
}
/* error */
static int _error(char const * message, int ret)
{
fputs("UWvbiosdump: ", stderr);
perror(message);
return ret;
}
/* usage */
static int _usage(void)
{
fputs("Usage: UWvbiosdump [-o output]\n", stderr);
return 1;
}
/* public */
/* functions */
/* main */
int main(int argc, char * argv[])
{
int o;
char * filename = NULL;
while((o = getopt(argc, argv, "o:")) != -1)
switch(o)
{
case 'o':
filename = optarg;
break;
default:
return _usage();
}
if(optind != argc)
return _usage();
return (_UWvbiosdump(filename) == 0) ? 0 : 2;
}