Statistics

Members: 1925
News: 292
Web Links: 1
Visitors: 3645487

Who's Online

Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
Pinczakko's Guide to Self-patching Expansion ROM Source Code
User Rating: / 1
PoorBest 
Written by Darmawan M S a.k.a Pinczakko   


Now, I'll show you an example of a self-patching ISA expansion ROM. This sample can be regarded as a template.

1. ISA Expansion ROM structure

It has been known widely that Expansion ROM or Option ROM is a binary file placed inside the ISA expansion card or PCI expansion card. It is also possible to place this ROM as a part of the motherboard BIOS. An ISA expansion ROM has the following structure:

  • It's a plain binary file.
  • Its size is a multiple of 512 bytes.
  • Its header has the following format:
    1. 55AAh ;this is the 1st and the 2nd byte, its a bootable code sign, it's actually AA55h, but Intel uses little endian that's why it's reversed.
    2. xxh ;this is the 3rd byte, where xx is the hex number that indicate the size of the rom in multiple of 512 bytes, e.g. for a 512 bytes rom it will be 01h.
    3. jmp ;Commonly this is the 4th through 6th byte, usually this is a near jump instruction that invoke the real initialization code of the rom.
    4. ret (far) ;the last byte in the header, it invokes a far return to pass the program execution back to the main bios (original.tmp), you can invoke it in the initialization part as well, so this is not a must have. See the example code for more info.
  • Its byte checksum is exactly zero, i.e. after all of its bytes summed and goes through modulo 100h operation, it's equal to zero.
On the other hand, PCI expansion ROM is developed based on the ISA expansion ROM structure with a couple of PCI specific data structure. I won't explain that here and I will only show you how to build an ISA expansion ROM for the moment. You will use only one tools, i.e. the Flat Assembler a.k.a Fasm.

2. Building a Self-patching ISA Expansion ROM

Now, I'll show you an example of a self-patching ISA expansion ROM. This sample can be regarded as a template.

;---------------------------------------------------------------------------------
; Pinczakko's ISA ROM patch template
;
; file : isa_rom_template.asm
;---------------------------------------------------------------------------------
use16  ; 16-bit by default
macro PATCH_PCI reg_addr,mask
{
mov     eax,reg_addr    ;fetch  addr of the regs to be patched
mov     dx,in_port      ;fetch input port addr of PCI cfg space
out     dx,eax
mov     dx,out_port 
in      eax,dx
or      eax,mask        ;mask the regs value (activate 
;certain        bits)
out     dx,eax
}
;---------------------------------------------------------------------
; Expansion ROM Header
;---------------------------------------------------------------------
ROM_SIZE_IN_BLOCK = 1  ; 1 means ROM size is 1 block (512 bytes)
ROM_SIZE_IN_BYTE = ROM_SIZE_IN_BLOCK * 512
db  55h                 ; Rom signature byte 1
db  0AAh                ; Rom signature byte 2
db  ROM_SIZE_IN_BLOCK   ; Rom Size in multiple of 512-bytes (1bit = 512 bytes)
call INIT           ; jump to initialization
retf                ; jump back to system BIOS
;----------------------------------------------------------------------
; equates
;---------------------------------------------------------------------
in_port         equ 0cf8h
out_port        equ 0cfch
ioq_mask        equ 00000080h
ioq_reg         equ 80000050h
bank_mask       equ 20000844h
bank_reg        equ 80000068h
tlb_mask        equ 00000008h
tlb_reg         equ 8000006ch
dram_mask       equ 00020202h
dram_reg        equ 80000064h
INIT:
pushad
PATCH_PCI ioq_reg, ioq_mask     ; patch the ioq reg
PATCH_PCI dram_reg, dram_mask   ; patch the DRAM controller i.e. the
; interleaving part
PATCH_PCI bank_reg, bank_mask   ; patch bank active page ctl reg
PATCH_PCI tlb_reg, tlb_mask     ;Activate Fast TLB lookup
popad
retn                            ;return to this rom's header
times (ROM_SIZE_IN_BYTE-$) db 0 ; use 00h as the padding bytes until we reach the ROM size
; The last byte (512th) will be the patch_byte for the checksum
; patch_byte is calculated and automagically inserted below
PREV_CHKSUM = 0
repeat $
load CHKSUM byte from %-1
CHKSUM = (PREV_CHKSUM + CHKSUM) mod 0x100
PREV_CHKSUM = CHKSUM
end repeat
store byte (0x100 - CHKSUM) at ($-1)  ; store the patch_byte

To compile the code above, do the following steps:
  1. Download Fasm for windows (Fasmw) from http://flatassembler.net
  2. Install Fasmw install fasmw into your computer. Actually all that you need is to copy its files.
  3. Run Fasmw and paste the code above into Fasmw code editor. Then save it to a file by clicking File|Save as...
  4. Compile the code by pressing Ctlr+F9. The compilation result will be placed in the same directory as the source code file that saved in the previous step. The name of the file is the same as the source code file with a *.bin extension if you are using Fasmw version 1.67 and it will have a *.com extension if you are using Fasmw 1.52. Both kind of files are a valid ISA expansion ROM. You can insert this file into the target BIOS file.
The result of the compilation of the source code above is shown below:

Address                          Binary                                                                    ASCII

00000000 55AA 01E8 0100 CB66 6066 B850 0000 80BA F80C 66EF BAFC 0C66 ED66 0D80 0000 0066 EF66 B864 U......f`f.P......f....f.f.....f.f.d

00000024
0000 80BA F80C 66EF BAFC 0C66 ED66 0D02 0202 0066 EF66 B868 0000 80BA F80C 66EF BAFC 0C66 ......f....f.f.....f.f.h......f....f

00000048
ED66 0D44 0800 2066 EF66 B86C 0000 80BA F80C 66EF BAFC 0C66 ED66 83C8 0866 EF66 61C3 0000 .f.D.. f.f.l......f....f.f...f.fa...

0000006C
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

00000090
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

000000B4
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

000000D8
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

000000FC
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

00000120
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

00000144
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

00000168
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

0000018C
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

000001B0
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

000001D4
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....................................

000001F8
0000 0000 0000 0004 ........


The secret recipe of the source code lies in:

times (ROM_SIZE_IN_BYTE-$) db 0 ; use 00h as the padding bytes until we reach the ROM size
; The last byte (512th) will be the patch_byte for the checksum
; patch_byte is calculated and automagically inserted below
PREV_CHKSUM = 0
repeat $
load CHKSUM byte from %-1
CHKSUM = (PREV_CHKSUM + CHKSUM) mod 0x100
PREV_CHKSUM = CHKSUM
end repeat
store byte (0x100 - CHKSUM) at ($-1)  ; store the patch_byte

This particular code is parsed by Fasmw "interpreter" after the code has been compiled. To put simply, it zero-extends the result of the compilation to ROM_SIZE_IN_BYTE and then it calculates the 8-bit sum of the binary and then appends a value in the end of the binary. This particular value is the 8-bit checksum of the binary file such that the 8-bit sum of the whole binary is equal to 00h.

The technique explained here is easily extended for PCI expansion ROM. You can use the automatic byte patching and checksum calculation above in your code to create a self-patching PCI expansion ROM. Of course, that's possible only if you use fasm ;-).