PDA

View Full Version : bios reversing


Vigual
July 31st, 2010, 15:01
I'm trying to find an particular series of instructions within the bios source I have. The instructions initialize the SMRAM. I know that this configuration must be initialized using the in/out instructions and that the immediate that is moved into the eax register during this initialization is something containing the string xx00009D, or something like that. THe problem is that the bios source code can't be directly disassembled into mneumonics. Instead, all I have to work with is opcode. I've tried searching for opcode that looks like the opcode for the instructions I want, but this hasn't worked so far. Any suggestions on how I can find these instructions, or even a general way to go about constructing code and data from opcode through the use of softice? Is there a name for the process of trying to construct code and data from opcode? If I know what it is called, Maybe I can find other forums that are dedicated to this process.

BanMe
July 31st, 2010, 15:53
Contact your bios manufacturer to see if they have a reference or two there..
Then with what information that can be gleaned from that search, do a search for bios modification ...

Sorry the only answer I have is for you to search more. :{

regards BanMe

Kayaker
July 31st, 2010, 20:42
Hi

You'll probably want to look into the Intel System Programming Guide Ch. 24 System Management Mode (SMM), and PCI programming

PCI Local Bus Specification Revision 3.0
http://fpga-faq.narod.ru/PCI_Rev_30.pdf

as well as some extra Intel docs specific for your system, i.e.

Intel® 82848P Memory Controller Hub (MCH) Datasheet


What you're probably seeing is the API (or equivalent of)

Code:

_WRITE_PORT_ULONG@8 proc
Port = dword ptr 4
Value = dword ptr 8

mov edx, [esp+Port]
mov eax, [esp+Value]
out dx, eax
retn 8
_WRITE_PORT_ULONG@8 endp


Where Value is your xx00009D (any chance it's 0x8000009C?)


What you probably want to look for is sequences with the values CF8h and CFCh, which are signatures for the standard CONFIG_ADDRESS/CONFIG_DATA register mechanism (CFCh/CF8h ports) as defined in the PCI Local Bus Specification. It is through this interface that you communicate with SMRAM.

What you need to do then is interpret what is being read/written through those PCI ports. IF you see the CFCh/CF8h signature then we're probably talking about the same thing and I can provide a few examples that might help interpret the "bits inbetween".

Why don't you post a short bit of code that encapsulates the IN/OUT instructions you're seeing?

Kayaker

Vigual
August 1st, 2010, 23:00
yeah, you're right Kayaker. I forgot that I'm supposed to be looking for 9C, not 9D, because I forgot the registers are dword aligned, or something like that.

Here is an example of the in/out set of instructions

Code:

db 66h
seg000:4E06 bswap edx
seg000:4E09 mov dx, ax
seg000:4E0B db 66h
seg000:4E0B bswap edx
seg000:4E0E mov al, 80h ; 'Ç'
seg000:4E10 mov ah, dh
seg000:4E12 db 66h
seg000:4E12 bswap eax
seg000:4E15 mov ah, dl
seg000:4E17 db 66h
seg000:4E17 bswap edx
seg000:4E1A mov al, dh
seg000:4E1C and al, 0FCh
seg000:4E1E db 66h
seg000:4E1E bswap edx
seg000:4E21 mov dx, 0CF8h
seg000:4E24 out dx, eax
seg000:4E26 shr eax, 8
seg000:4E2A mov dx, 0CFCh
seg000:4E2D xchg eax, ebx
seg000:4E2F in eax, dx
seg000:4E31 xchg eax, ebx
seg000:4E33 db 66h
seg000:4E33 bswap edx
seg000:4E36 xchg ax, dx
seg000:4E37 jmp di




It's kind of hard to tell which port is being read. I think the way pci configuration works is that, whatever port number is contained in the eax register when the "out" instruction is executed, is the register that is sending data to the eax register when the "in" instruction is executed. Kind of hard to tell because the port isn't an immediate. Also, searching the bios code for 9C 00 00 or 9C 00 00 80 byte sequence isn't effective in this case. What port do you think these instructions are working on? (I think the code above the bswap instruction is probably another hardware configuration, so i think something jumps to the bswap instruction, starts executing from there.)

Kayaker
August 2nd, 2010, 01:11
It's a little hard to tell from this snapshot, but I think we can make a few assumptions.

Opcode 66h is defined as a Operand-size override prefix or Precision-size override prefix.

BSWAP is defined as
Changes the byte order of a 32 bit register from big endian to little endian or vice versa. Result left in destination register is undefined if the operand is a 16 bit register.

So the 66h is part of the bswap instruction in this case. If written in 32 bit code, bswap edx = 0F CA. In bios code it's 66 0F CA.


We can't really tell what was in eax/edx at the start of this code, but if we look at the known parts of the instructions

mov al, 80h
bswap eax

eax will be 80000000 after executing these 2 instructions (assuming the rest of the register bits were 0).

Now let's go down to the next part

mov al, dh
and al, 0FCh

I'm going to make a leap of faith here and say dh contains 9D (I'll explain why in a minute).
So eax is already 80000000
then it becomes 8000009D after mov al, dh
after the AND instruction it becomes 8000009C.


Aah, 8000009C is familiar right?

The next instructions write the value of eax = 8000009C to PCI port CF8. This is equivalent to the WRITE_PORT_ULONG API.

mov dx, 0CF8h
out dx, eax




Now if we look at the Memory Controller Hub (MCH) Datasheet (for my 82848P system it's in section 3.5 DRAM Controller/Host-Hub Interface Device Register Address Map) we find that 0x9D is the address offset for the SMRAM System Management RAM Control Register (Device 0). The SMRAMC register controls how accesses to Compatible and Extended SMRAM spaces are treated. A little further down are details of each of the bits in the register.


Here's a little snippet which simply reads the complete contents of the SMRAM register. You should be able to see where the 0x8000009C comes from. In this code it's the CONFIG_CMD macro, in your bios code it's embedded within all those cryptic bswap instructions and the final 'and al, 0FCh'.


Code:

#define MCH_SMRAM 0x9D // SMRAM System Management RAM Control

#define CONFIG_ADDRESS 0x0CF8 // Configuration Address Register
#define CONFIG_DATA 0x0CFC // Configuration Data Register

#define CONFIG_CMD(bus, dev_fn, where) \
(0x80000000 | (((ULONG)(bus)) << 16) | (((dev_fn) & 0x1F) << 11) | (((dev_fn) & 0xE0) << 3) | ((where) & ~3))
// 0x80000000 enables CONFIG_ADDRESS Configuration Enable (CFGE) bit 31

/* alternate definition
#define CONFIG_CMD(bus, dev_fn, where) \
(0x80000000 | (bus << 16) | (dev_fn << 8) | (where & ~3))
*/

////////////////////////////////////////////////////

ULONG Bus = 0;
ULONG Device = 0;
ULONG Register = MCH_SMRAM; // SMRAM System Management RAM Control 0x9D

ULONG Original_CONFIG_ADDRESS;
ULONG current_MCH_SMRAM;

////////////////////////////////////////////////////

// DbgPrint("%08X\n", CONFIG_CMD(Bus, Device, Register)); // 0x8000009C

// Save original Configuration Address Register (0x0CF8) value
Original_CONFIG_ADDRESS = READ_PORT_ULONG((PULONG)CONFIG_ADDRESS);

// Specify which address to read/write to by writing to Configuration Address Register
WRITE_PORT_ULONG((PULONG)CONFIG_ADDRESS, CONFIG_CMD(Bus, Device, Register));

// Read result from Configuration Data Register
current_MCH_SMRAM = READ_PORT_ULONG((PULONG)CONFIG_DATA);
// DbgPrint("MCH_SMRAM %08X\n", current_MCH_SMRAM); // MCH_SMRAM 0038_0A_00

// 0A 1010 bits 1 3 set
// bit 2:0 C_BASE_SEG - hardwired to 010
// bit 3 Global SMRAM Enable



And here's what that sequence looks like disassembled

Code:


mov ebx, ds:__imp__READ_PORT_ULONG@4

mov edi, 0CF8h
push edi ; Port
call ebx ; READ_PORT_ULONG(x)
mov [Original_CONFIG_ADDRESS], eax

mov esi, ds:__imp__WRITE_PORT_ULONG@8

push 8000009Ch ; Value
push edi ; Port
call esi ; WRITE_PORT_ULONG(x,x)

mov ebp, 0CFCh
push ebp ; Port
call ebx ; READ_PORT_ULONG(x)
mov [current_MCH_SMRAM], eax



The expanded versions of those API's as you see in the bios code are:

Code:

_WRITE_PORT_ULONG@8 proc
Port = dword ptr 4
Value = dword ptr 8

mov edx, [esp+Port]
mov eax, [esp+Value]
out dx, eax
retn 8
_WRITE_PORT_ULONG@8 endp


_READ_PORT_ULONG@4 proc
Port = dword ptr 4

mov edx, [esp+Port]
in eax, dx
retn 4
_READ_PORT_ULONG@4 endp



Hopefully this gives you an idea of how such a sequence is written in "normal" 32 bit code, and how it equates to the type of thing you might be seeing in the bios code.

Errmm, I've been sort of side stepping this, but while there are valid reasons for 'initializing SMRAM' as you put it, this is also exactly in the realm of SMM rootkit code and is why I'm familiar with the details. Is there any chance this is actually what we're talking about here?

Kayaker

Vigual
August 2nd, 2010, 09:23
Wow, you really know your stuff. I'm not trying to develop an SMM rootkit. I couldn't, even if I wanted to. I don't have that level of skill. I need to unlock the SMRAM for a different purpose. Thank you so much for your help, Kayaker.

FrankRizzo
August 2nd, 2010, 17:27
I assume you already know this, but just in case. You can't unlock SMRAM once it's been locked. So, what you're trying to do is to stop it from being locked in the first place.

Depending on the persistence of what you're doing, I could maybe help you. You say you're not doing a rootkit. That's good, can you elaborate a little more on what you ARE doing?

Vigual
August 3rd, 2010, 09:30
Quote:
[Originally Posted by FrankRizzo;87438]I assume you already know this, but just in case. You can't unlock SMRAM once it's been locked. So, what you're trying to do is to stop it from being locked in the first place.

Depending on the persistence of what you're doing, I could maybe help you. You say you're not doing a rootkit. That's good, can you elaborate a little more on what you ARE doing?


I thought that you could write to SMRAM whenever you wanted to, as long as you unlocked the D_LCK bit and set the SMRAM to Open. Do you remember where you read that the SMRAM can only be locked once?

I'm trying to write an extension for a virtual machine, and the extension needs to run in SMM mode.

FrankRizzo
August 3rd, 2010, 17:35
Quote:
[Originally Posted by Vigual;87445]I thought that you could write to SMRAM whenever you wanted to, as long as you unlocked the D_LCK bit and set the SMRAM to Open. Do you remember where you read that the SMRAM can only be locked once?

I'm trying to write an extension for a virtual machine, and the extension needs to run in SMM mode.


Google this "D_LCK SMRAM", and choose any of the top results there. I've been working on SMRAM at the office for the last few months. TRUST ME on this. Once D_LCK is set, it's set until the next reboot.

Vigual
August 3rd, 2010, 18:03
Wow. I can't believe I haven't seen that paper before. I'm going to throughly read the section on circumventing the D_LCK bit. Thanks for the advice.

FrankRizzo
August 3rd, 2010, 18:09
Quote:
[Originally Posted by Vigual;87447]Wow. I can't believe I haven't seen that paper before. I'm going to throughly read the section on circumventing the D_LCK bit. Thanks for the advice.


Definitely read the part about how the exploit only works on certain old boards, and how Intel has fixed it on the newer ones.