Salihun Award BIOS
Salihun Award BIOS
2 (2005)
http://www.CodeBreakers-Journal.com
E-Mail: mamanzip@yahoo.com
* Corresponding Author
Received: 07. Mar. 2005, Accepted: 10. Mar. 2005, Published: 20. Mar. 2005
Abstract
This tutorial is intended for people who already done some award bios modification before, and already knows
the core component of award bios. In case you haven't done it or haven't know anything yet, you can read
somewhere else. I have provided links to bios related website in the front page of this website and also I've made
tutorial called Preliminary Bios Modification Guide and Mainboard Bios Components. As the title said, what I'm
going to explain here only apply exactly to Award Bios version 4.51PG. However, the principle of this
modification can be applied to other bioses as well, provided that you have enough knowledge in assembly
language and using disassembler. As usual, I didn't held any responsibility in the damage that may occur if you
apply the steps explained here, proceed at your own risk, you have been warned. I'd like to thank to Petr Soucek
for his inspiring tutorial, Gigabyte ga586hx bios modification. I'm indebted to him for opening my eyes about
what could possibly be done to the award bios file.
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
1. Introduction
OK, let's get down to the business. I'm using Iwill VD133 (the slot 1 version) mainboard as my
testbed. This mainboard uses award bios version 4.51PG dated 28 July 2000. In this article I'll explain
how to do "bios code injection", i.e. injecting our patch into original.tmp (system bios) file. The area
in original.tmp that we are going to inject with code is somewhere around memory test area code
which is part of the POST (Power On Self Test). This area is right above the area which handles hdd
initialization as described by Petr in his article. We will need these software tools:
1. Modbin. I'm using the version 4.50.80C. Your bios requirement may vary.
2. Cbrom. I'm using the version 2.08. Your bios requirement may vary. Cbrom and modbin are
available for download at http://www.biosmods.com.
3. A binary file editor (hex editor). I'm using Hexworkshop version 3.0b.
4. Award Bios Editor version 1.0 or another tool/trick that enables you to extract and replace
original.tmp from the motherboard bios with the modified version. Award Bios Editor version
1.0 are available for download at http://awdbedit.sourceforge.net.
5. A disassembler. I'm using ndisasmw.exe which comes with nasmw version 0.98. This is the
windows version of the disassembler that comes with netwide assembler package, it's availabe
for download at http://nasm.sourceforge.net.
6. An assembler and its linker. I'm using microsoft macro assembler (Masm) version 6.15 and its
linker i.e. LINK version 5.60.33, this linker still support emiting 16 bit Intel binary. I'm using
it since sometimes nasm emit 16 bit code that is not suitable for my computer, which
sometimes end up with a lock up during POST. It's available for download at
http://win32asm.cjb.net (in the download section).
Now we are armed with the right tools. What we need to do next are summarised below :
1. Extract original.tmp from the bios file somewhere so that we can edit it separately.
2. Disassemble original.tmp and look for code spot(s) where we can inject our code.
3. Build our own code then inject it into original.tmp and then replace some of original.tmp code
so that our injected code will be executed upon booting, or completely replace "unneeded"
procedure(s) in original.tmp
4. Replace original.tmp in the mainboard bios file with the modified one.
WARNING: The explanations in this section remain valid, however, there is stability issue with this
approach in my testbed. Read more about this issue here. In conjuction with the issue, I strongly
recommend you to read this section first before proceeding, since it contains fundamental tricks that
are used throughout this article.
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
I just do some clicking on the related menus to do this. Here how it's done: select the system bios item
in the tree on the left then open up action menu then select Extract File menu and proceed at your will.
Be sure to place builtins.dll in the same directory as awdbedit.exe. We need this since upon starting,
awdbedit scans the directory in which it's located for plugin. builtins.dll is the main plugin which
provided the capability to recognize core (and some extended) award bios components, such as
original.tmp, the epa file, etc. Note that the awdbedit that I'm using already been compiled several
times and undergone some cosmetic patches, since the version from sourceforge site uses "annoying
size" fonts which displays horrible in my small CRT monitor. Below is the screenshot of award bios
editor that I'm using:
Open up the extracted original.tmp from previous step in your hexeditor, then examine it. Here's a
snapshot from Hexworkshop that I'm using:
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
To successfully disassemble this file we need some common sense and intelligent guesses. I used this
guide :
• Use your logical sense to examine the disassembly result. Does it makes sense at all, if not
then you are in the wrong direction, you don't skip some parts that suppose to be a data
section, not code section, if this is the case then the disassembler will emit a strange looking
assembly code. You can use the next guide(s) to help you against this.
• The majority of ascii string are terminated with binary zero, i.e. displayed as 00 in the
hexadecimal value above.
• Some ascii string are terminated by '$' character or 24 hexadecimal.
• Some ascii string are simply "discarded" by "unconditionally jumping" through it.
• Due to 1,2, and 3 we have to instruct the disassembler to skip through this ascii string, so that
we get the real instruction.
• Some instructions possibly executed in 32 bit mode, such as the memory detection routine.
This is logical since AFAIK, to access memory after 1 MByte we need to activate gate A20
and to access several hundred megabytes (as in our daily case) we need 32 bit mode. I even
get into speculation that the current award bios (version 4.51PG, version 6.0PG and version
6.0) might already setup data structures needed to operate x86 in 32 bit protected mode such
as GDT and temporarily switch into protected mode to accomplish this, and then switch back
to 16 bit real mode for compatibility reason. This should be taken into account, hence we have
to be very careful and just place our 16 bit code(s) wherever we are sure that the processor
operating mode still in 16 bit real mode. After spending some more time disassembling the
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
POST routine, I found that my suspicion prove to be correct, the memory detection routine
have switched the machine into protected mode momentarily!
• The last 64 Kbytes of original.tmp have a checksum that is calculated by substracting every
bytes in advance from 10000h until 1FFFFh and it is placed in the last byte.
• The first 64 KBytes of original.tmp seems to contain POST (Power On Self Test) code. Due to
this reason, this time we'll examine only the first 64 Kbytes and inject our code there. In my
experience, the end of this 64 Kbytes contains lots of padding FFh bytes and 00h bytes
(around 4 Kbytes, i.e. from around F000h to FFFFh), we can place our code there. I have one
more reason to place the code there, based on my experience too, it seems that this end of the
first 64 Kbytes area is free from checksum related issue. Generally the first 64 Kbytes are also
free from this checksum issue, i.e. the first 64 KBytes is not subject to checksum calculation
as in the case of the last 64 KBytes mentioned above.
Based on the guide above, we disassemble original.tmp using ndisasmw.exe. Since I was bored
enough to type such a massive command in the command line, we are going to use a windows batch
file as follows :
1. Examine its content in your hexeditor then split them into parts and grow the parts (increase
the part size) as needed as you trace through the part's disassembly result. Most of the time
this is needed due to branch instruction such as variation of jump and call instructions. In the
beginning, original.tmp is big enough to make you discouraged doing a disassembly on it in
one shot. Note that I only disassemble the first 64 Kbytes to achieve my modification.
2. Below is an example of the content of a batch file that I'm using :
@echo off
ndisasmw.exe -b16 -k 0,0xE3 -k 0x106A,0x3F -k 0x2E76,0xA -k 0x2F2F,0x16
-k 0x328D,0x2B -k 0x43E0,0x360
-k 0x5D5D,0x52 -k 0x7063,0x33 sys_part.bin >> sys_part.txt
o sys_part.bin is a file that contain part of the original.tmp, it contains much less code.
o the -k xxx,yyy switch is used to skip bytes that I suspect to be data section, not code
section.
o the -b16 switch is used to tell the disassembler to treat the binary as 16 bit codes.
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
In the upper part, you can see that I skipped some bytes that clearly shown as "readable ascii
string" in my hexeditor. This string ends up with a terminating zero (00h), so I'm pretty sure of
what I'm doing.
The lower part of the snapshot above shows similar code to what Petr Soucek describe in his
bios modification article, i.e. hdd identification routine. This puts me into better position to
apply my "code injection".
1. We are going to search for 3 bytes instruction in the first 64 KByte area to be replaced by a
near call instruction into our injected code
2. The injected code will be placed at EFF0h address. We are replacing FFh bytes there as
needed.
3. The majority of our code will be generated by a 16 bit capable assembler and linker, and then
we will need to "hand tune" it to suit our purpose, since sometimes our assembler and linker
simply emit code that isn't suitable to our needs. We are going to name our patch code file
sys_patch.asm
Now we have the plan, but before proceeding further we have to take care some cautions. Note that
sys_patch.asm are assembled using masm615 with LINK version 5.60.339. We have to take some
protective measure to protect ourself against bad code as follows:
Masm615 doesn't emit 3DFFFFh binary for this code (which is the original code in the
original.tmp file) . Hence, I have to replace that 3 bytes which Masm615 emits with the
suitable code (3DFFFFh) using hexeditor. Things like this have to be taken into account when
patching original.tmp.
• Beware of registers and instructions you are using. I strongly recommend to save flags and
every register your code uses before executing your injected code and restore them back prior
to returning to the real original.tmp code. If you fail to do so, there's a big chance you'll screw
up your system. You've been warned.
• We have to avoid intersegment call as entry point into our injected code, since this tend to put
us in trouble. That's why we decided to put our injected code in the first 64 KByte area, so that
we stick to intrasegment near call as our entry point.
• If you replace the original code in original.tmp with 3 bytes of call instruction to your injected
code, be sure to calculate the relative distance between the call and your injected code VERY
CAREFULLY, near call instruction distance are measured as follows:
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
For example, the near call instruction located at D79h and your injected code begins at EFF0h
then the relative_call_distance will be :
, since the call instruction itself uses 3 bytes. Hence you have to replace the original 3 bytes of
code with a near call instruction i.e. E8 74 E2, the distance bytes are reversed since intel x86
uses little endian scheme.
• Don't forget to include the replaced code (the 3 bytes of code which you replace with a call
instruction) in your injected code prior to returning. Generally your injected code will looks
like:
• Don't forget that we are targeting 16 bits real mode environment. I'm using the following
command to assemble the file:
Note: You don't need to pay attention to the linker warning, it has no effect to us since we are
not building a real *.com file, we are targeting 16 bit pure binary code. The command above
will end up buiding sys_patch.bin as the resulting binary file that we are going to use.
Then we proceed to search for the code to replace. Petr Soucek in his article points out about the hdd
initialization routine, we are going to place our code just above that code. The disassembly result of
my bios around that code as follows:
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
Then proceed to look where we can place our injected code. In my case, I found the suitable area
beginning at EFF0h. The following is the hex dump of my original.tmp around that area :
As you can see, these are just padding bytes. The FFh bytes continues until FFFFh address. So, I'll
just place my code beginning at EFF0h. Now we proceed to build our injected code. Here's the listing
of my code:
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
; restore register contents and call the replaced instruction prior to return
popfd
pop edx
pop ebx
pop eax
cmp ax,0ffffh ; This is the instruction that we replace in the POST code
ret ; return and proceed to the next initialization code
INIT ENDP
CSEG ENDS
END
There are some things that we have to note here. First, every branching instruction is a near branching
instruction which uses relative address. Second, we are telling the assembler to emit 16 bits code.
Third,we preserve all the register status during our injected code execution, I've been bitten by
forgetting to preserve dx register during my code injection experiment, I learn a lot from it :-). The
resulting binary from the code above as follows:
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
The disassembly of this binary using " ndisasmw.exe -b16 sys_patch.com > sys_patch.txt " as follows:
Looking at the resulting binary and its disassembly result, we know that we need to replace the code
that is not supposed to be like that by using hex editor. But we have to ensure that the amount of bytes
we are replacing is the same with the assembled version, if not, then all the branching instruction will
be screwed up. Fortunately we have 3 bytes to be replaced with also 3 bytes instruction, so this
shouldn't be a problem. Now, we replace the 83 F8 FF bytes with 3D FF FF bytes which is the
"correct instruction" based on what our previous bios code does. The resulting hex dump and
disassembly as follows:
Hexdump:
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
Disassembly:
Then we proceed to inject our code into the area that we mentioned above. It's very easy, just
paste our binary into that area using a hex editor. But before that, be sure to remove the same
amount of FFh bytes in that area as the size of our binary, in my case, this is 60h bytes. Here's
the resulting hex dump:
Now, as our last step in this section is replacing the original code with a call into our injected code.
First, we have to calculate the intrasegment distance as follows :
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
Second, we make the binary for the call instruction. That would be: E8 74 E2 , the distance value is
reversed, since intel x86 uses little endian scheme. Note that call instruction distance is calculated
relative to the next instruction after the call instruction itself, that's why we are using D7Ch above, not
D79h, keep this in mind.
Third, replace the code in address D79h with our code, i.e. E8 74 E2 using our hex editor. The
resulting disassembly after replacing that code will be:
Well, now we have done what we want to original.tmp, this completed our steps in this
section.
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
The modification that we are going to do in this part is similar to what described above, in Hacking
Steps in Detail. The difference is in the part of the original bios code (original.tmp) that we are going
to replace with a call into our code. This hack also will incorporate some complexities of the call
instruction itself. I will only highlights the differences here, I'm not going to repeat what I've explained
above.
We proceed through the steps mentioned above until we arrive at Disassembling original.tmp. In this
step, the code spot where we are going to place our call into the injected routine is around 2A0h. I'm
not so sure what this area of code doing, but one thing for sure, this is still part of the POST code area.
Below is the disassembly of this part in my bios :
The majority of the code that we are going to inject is still the same. Only one different, we
are substituting the cmp ax,0ffffh code with a call instruction like what is highlighted in
the disassembly result above, but we need some trick to achieve that. The listing as follows :
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
; restore register contents and call the replaced instruction prior to return
popfd
pop edx
pop ebx
pop eax
call PATCH_PCI ; !!!WARNING!!!Replace the target of this call with the
default from the real bios
ret ; return to instruction after the code that we replace in
system bios
INIT ENDP
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
mov dx,0cfch
in eax,dx
or eax,ebx ; mask the regs value (activate certain bits)
out dx,eax
ret ; return to initialization code above
PATCH_PCI ENDP
CSEG ENDS
END
as you can see from the code highlighted above, we are placing a "dummy call" there so that the
assembler can assemble our code. If we don't do so, it will complain and say that we are calling non-
existent routine. We are going to replace the target of that call instruction manually by using hex
editor. The resulting binary and its disassembly as follows :
Hex dump :
Disassembly result :
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
Now, we only need to insert our code into EFF0h and then do some "address fixups". This is tricky
step . I accomplish it as follows :
1. First, insert our code into original.tmp. We do this to ease the process of calculating the
relative addresses that we are going to do next. The hex dump is below :
2. Second, calculate all the "fixup" addresses for the call instructions by using the formula in the
Hacking Steps in Detail above. We got the following results :
o Relative address for entry point into our code at 2EAh :
relative_addr = addr_of_our_code - addr_after_the_call_at_2EA
relative_addr = EFF0h - 2EDh
relative_addr = ED03h
o Relative address for the call instruction that we replace at 2EAh. This call is placed
inside our injected code as highlighted in hex dump above. The "address fixup"
calculation as follows :
relative_addr = addr_of_old_call_target - addr_after_call_at_our_code
relative_addr = 12E9h - FO3Fh
relative_addr = - DD56h
relative_addr = 10000h - DD56h
relative_addr = 22AAh
The call instruction in intel x86 is a signed call instruction, that's why we use the
above formula to calculate the "backward" call instruction in our code. This is
working as expected , I've tested it and it's good :-).
3. The last step is to encode the instruction we need and insert them into the appropriate places.
The first call instruction encoded into E8 03 ED h, the second call instruction encoded into E8
AA 22 h. Place the first call beginning at 2EAh and the second at F03Ch. The resulting hex
dump is below :
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
Note that I've changed the last 8 bytes of FFh bytes with 00h bytes. This is just for fun :-).
That's it, we've done with this third step.
The next steps proceed exactly the same as what described above in Hacking Steps in Detail. After
applying those steps, we are done and ready to flash the modified bios.
Note that I have to switch to an older version bios for my mainboard to accomplish this, since my
mainboard's latest bios incorporated a different method which doesn't execute the "legacy EPA
procedure" at all . I know this, since I've replaced the legacy code that happens to be still included in
that bios's original.tmp, but nothing happen, so I conclude it must be in different part of the bios and
might be in different bios component. This method displayed full size customized image during boot,
not only full sized logo but also customized POST indicators on top of the full sized image. Due to
this, the target bios that I'm using is an older one, dated 24th February 2000 and uses the "legacy EPA
procedure". Things like this have to be taken into account in case your bios also structured like my
latest mainboard bios, i.e. using a "customized EPA procedure" which is not located in the "legacy
EPA procedure code spot".
The steps that we'll use here is similar to the steps in Hacking Steps in Detail, except that we are not
only replacing one line of code but the entire procedure and also we are not placing any "injected
code" in the last 4 KByte of the first 64 Kbyte of the bios code (original.tmp).
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
Now, the details. The hex dump around that procedure in my bios as follows :
00001F00 C706 1A04 1E00 1E00 9DF8 C390 808E E101 ................
00001F10 10F6 4614 3074 01C3 061E 60BE 0060 BF00 ..F.0t....`..`..
00001F20 3AB9 0030 E85A 4EC6 86ED 0155 B812 00CD :..0.ZN....U....
00001F30 10FC B800 008E C0BF 0070 B820 07B9 D007 .........p. ....
00001F40 F3AB BE0C 0AE8 B64C 0AC0 7416 BF04 00E8 .......L..t.....
00001F50 774E B800 408E D866 813E 0000 4157 424D wN..@..f.>..AWBM
00001F60 7422 C686 ED01 00BF 0C00 E85C 4EB8 0040 t".........\N..@
00001F70 8ED8 6681 3E00 0041 5742 4D0F 856B 00C6 ..f.>..AWBM..k..
00001F80 86ED 01AA B801 12B3 36CD 1033 D280 BEED ........6..3....
00001F90 01AA 7503 BA10 0033 C980 BEED 01AA 7503 ..u....3......u.
00001FA0 B9E0 01E8 2F01 80BE ED01 AA74 1403 0E04 ..../......t....
00001FB0 0081 F980 0272 EC03 1606 0081 FAD0 0172 .....r.........r
00001FC0 D6E8 9F00 B800 12B3 36CD 1080 BEED 01AA ........6.......
00001FD0 7418 C686 ED01 AABE 8942 E823 0F74 03BE t........B.#.t..
00001FE0 C442 E846 02C6 86ED 0155 80A6 E101 EFBE .B.F.....U......
00001FF0 003A BF00 60B9 0030 E886 4DB8 0000 8ED8 .:..`..0..M.....
00002000 C606 9004 0061 1F07 C380 BEED 0155 7452 .....a.......UtR
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
; Macro definition
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
INIT ENDP
db 8Fh dup (90h) ; fill the remaining "code space" with nop instruction
CSEG ENDS
END
; -------------------------- END OF patch.asm -------------------------------------
00000000 669C 6660 FA66 B850 0000 80BA F80C 66EF f.f`.f.P......f.
00000010 BAFC 0C66 ED66 0D80 0000 0066 EF66 B864 ...f.f.....f.f.d
00000020 0000 80BA F80C 66EF BAFC 0C66 ED66 0D02 ......f....f.f..
00000030 0202 0066 EF66 B868 0000 80BA F80C 66EF ...f.f.h......f.
00000040 BAFC 0C66 ED66 0D44 0800 2066 EF66 B86C ...f.f.D.. f.f.l
00000050 0000 80BA F80C 66EF BAFC 0C66 ED66 83C8 ......f....f.f..
00000060 0866 EFFB B812 00CD 1066 6166 9DC3 9090 .f.......faf....
00000070 9090 9090 9090 9090 9090 9090 9090 9090 ................
00000080 9090 9090 9090 9090 9090 9090 9090 9090 ................
00000090 9090 9090 9090 9090 9090 9090 9090 9090 ................
000000A0 9090 9090 9090 9090 9090 9090 9090 9090 ................
000000B0 9090 9090 9090 9090 9090 9090 9090 9090 ................
000000C0 9090 9090 9090 9090 9090 9090 9090 9090 ................
000000D0 9090 9090 9090 9090 9090 9090 9090 9090 ................
000000E0 9090 9090 9090 9090 9090 9090 9090 9090 ................
000000F0 9090 9090 9090 9090 9090 9090 90 .............
The disassembly of the code around that area after manual modification using a hex editor as follows :
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
The rest is just exactly the same as the previous modification explained in Hacking Steps in Detail and
in the A More Radical original.tmp Hacking. That's it and we're done :-).
-- Update --
Finally I managed to mod my mainboard's latest bios that uses "custom EPA procedure" as mentioned
above. In that bios binary, I found a custom BIOS component that responsible for the "custom EPA
procedure", however it still contain the "legacy EPA procedure" in it's original.tmp. Below is output
from unmodified version of that BIOS :
As you can see, there's a component called ROS ROM. I found that this component responsible for the
custom EPA procedure. Extracting this bios component can be done by excuting :
I don't have enough time disassembling and dissecting this component, hence I only extract it and
looking at it's binary contents using hexeditor. A quick read over this binary confirm my suspicion.
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
Then I just release this component from that bios and then "patch" the "legacy EPA procedure" in its
original.tmp. Releasing this component is achieved by invoking :
To ensure that my goal to patch my BIOS will be achieved, I decided to flash the mainboard bios that
has no more ROS ROM and see what happens. As predicted, the bios "fallback" to executing "legacy
EPA procedure". However, we have 2 jobs to accomplish. First, to replace the EPA procedure and
second, to ensure that the old "custom EPA procedure" is not called anymore, since if it's called,
there's possibility our "modified EPA procedure" will not be called, you'll see the reason very soon.
The "legacy EPA procedure" in my bios located between 1F1Ch and 200Bh. The disassembly as
follows :
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
I replace this "legacy EPA procedure" with my code. The listing of the code as follows :
; Macro definition
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
; set video mode to 640x480 pixel, 16 color and clear video buffer (assumed to
be VGA Bios)
mov ax,12h
int 10h
CSEG ENDS
END
; -------------------------- END OF patch.asm -------------------------------------
I use hexeditor to replace the "legacy EPA procedure" in my mainboard's original.tmp with the
assembled code. Now, to ensure the old "custom EPA procedure" won't be called, we look for a call to
the epa procedure in the disassembly of the first 64 KB original.tmp code (segment E000h). I found it
at address 1E56h in my mainboard's latest bios. The disassembly as follows :
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
I came across the above commented code after comparing my mainboard's latest bios (which has
"custom EPA procedure") and its older bios which has no "custom EPA procedure". The disassembly
of the bios without "custom EPA procedure" as follows :
so, to achieve our second goal, just replace the unneeded instruction with a nop (90h) instruction by
using hexeditor. The disassembly of the patched code as follows :
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.
Vol. 2, No. 2 (2005), http://www.CodeBreakers-Journal.com
The rest is just exactly the same as the previous modification explained in Hacking Steps in Detail and
in the A More Radical original.tmp Hacking. I suspect that every mainboard with a custom EPA
procedure might conform to the structure that I explained here, i.e. having a "custom EPA procedure"
and a "legacy EPA procedure". Due to this reason we could possibly mod any Award BIOS by using
the method I explained here, it's your job to confirm this :-).
WARNING: After reading the last method described above, we might be tempted to replace the
"custom EPA procedure" with call to our own "injected" procedure somewhere in the first 64 KByte
(E000h segment) and left the "legacy EPA Procedure" to handle the "EPA display procedure".
However, further experiment in my system reveals that the so called "legacy EPA procedure" above
(which is in my mainboard's latest bios) is an incomplete "EPA procedure". I've try it and found that
even the "legacy EPA procedure" is "partially embedded" in the "custom EPA procedure", hence the
result is complete lock up during boot. We have to take this into account when doing this kind of
modification. The conclusion is: if you want to mod a custom EPA procedure, you have to completely
replace it to be safe or trace it thoroughly before modifying it, if you just want to modify it without
completely replacing it. I prefer to replace them all with my own code and "save some clockcycle" by
not doing the eyecandy that appear ugly to me :-) since VGA card related routine tend to be slow.
5. Closing Note
Some of the reader might ask, why I only replace the "exactly 3 bytes of code" instruction with a call
into my code in the first two modification method above? The reason is plain and clear, to minimize
the effect of the code that we inserted into the bios. I can mess up with 4 bytes instruction and place a
nop instruction ( 90h ) after the call into my code (which occupy 3 bytes), but I refuse to do so, since
I've been experiencing a lockup with that approach in my machine. Logically, it shouldn't happen, but
this is a peculiarity that needs more investigation.
If you want a bulletproof original.tmp hacking method, then I suggest the last method. If it's not
possible at all in your bios, you can stick to the basic principle, i.e. look for "cosmetic procedure" and
replace it with your own code. This is the safest method that I can suggest. If you are an experienced
hacker, then you might find a better method. What I write here is only a humble solution to my
problem. I'm not an experienced hacker in "direct hardware programming", I'm a newbie in this field :-
(.
My main reason "screwing up" with original.tmp is the "isa option rom trick", that I previously
employed sometimes not working with my "LAN card in disguise" (which is actually a SCSI
controller) if the isa option rom is assembled by using assembler other than masm 6.11 and masm
6.15. The code that masm emit is somehow weird, I can't decode it, it seems to be undocumented
opcode :-(. You can read about my "LAN card in disguise" stuff here.
That's all, I hope this would be useful for you. I have no testbed yet available for award version 6.0PG
bioses :-(. However, I've just began dissecting and disassembling them. If you have found something
wrong in this article or have developed new bios hacking trick based on what I explain here, please let
me know.
Copyright 2005 by the author and published by the CodeBreakers-Journal. Single print or electronic copies for personal use only are
permitted. Reproduction and distribution without permission is prohibited. This article can be found at http://www.CodeBreakers-
Journal.com.