02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework

This passage traced the setting-up of LAMP server and some ML&AI relevant knowledge in our attempt to detection malicious operation in UEFI environment.

(1) Bridge Connection in QEMU and VirtualBox

The TUN is a virtual networking device in 3rd layer in OSI model (which is able to transmit data using IP packets), and TAP is that in 2nd layer (which is only able to use MAC address for direction)

  • check the tun device in the OS
    Some tools including tunctl are required.
    (KVM连载)4.4.2 使用网桥模式(BRIDGE NETWORKING MODE)
  • build and setup the bridge
brctl addbr br0    #添加br0这个bridge
brctl addif br0 eth0    #将br0与eth0绑定起来
brctl stp br0 on     #将br0加入到STP协议中
dhclient br0    #将br0的网络配置好
route   #参看路由表是否正常配置
dmesg # 查看网桥启动信息

Note that the bridge is set up with promiscuous mode in default, which means that the bridge will receive all the data available from the network. And by enabling STP(Spanning Tree Protocol), the networking disconnection caused by circular architecture can be avoided.

  • start QEMU with bridge
    Simply deploy the interface name of the TAP devices. If the interface does not exist, it will be created by qemu automatically.
    vtpm-support/qemu-tpm/x86_64-softmmu/qemu-system-x86_64 -display sdl -m 1024\
    -net nic,model=pcnet,vlan=0 -net tap,vlan=0,ifname=tap1,script=/etc/qemu-ifup,downscript=no \
    -boot c -bios $BIOS/OVMF.fd -boot menu=on -tpmdev \
    cuse-tpm,id=tpm0,path=/dev/vtpm0 \
    -serial file:/home/hecmay/debug.log -global isa-debugcon.iobase=0x402 \
    -device tpm-tis,tpmdev=tpm0 edk2/Build/test.img

We can also set up the TAP device manually

  • Linux WiKi: Tap Networking With QEMU
  • qemu虚拟机通过tun/tap上网
  • Linux下虚拟网卡(tap)安装方法
  • VMware虚拟机三种网络模式详解
    The main concept is to use the bridge as a second-layer switch which connects the networking devices in VLAN together. The switch is created in form of a virtual networking device in host OS.
02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第1张图片
The Data Transmission in Bridge Mode
  • Limitation in UEFI DHCP Env with QEMU
    Without checking how the DHCP configuration in UEFI is realized, I found that the multiple guest OS will fail to communicate with each other even being started up with bridge mode in QEMU.

    So I simply set up the network with a nesting structure of bridge mode, which means that the virtual networking device of Ubuntu Guest OS will act as the new switch and create a new VLAN with QEMU Hypervisor.

    Also note that the Windows 7 OS will be unreachable from other machines in the LAN with default firewall setting.

    • Ubuntu虚拟机ping不通win7宿主机怎么办
02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第2张图片
Reaching Top Layer Host OS from 3rd Layer UEFI

(2) LAMP Server and Fundamental Usage of Apache

Fundamentals of HTTP protocol and establishment of connection between server and client:

  • 解读爬虫中HTTP的秘密(基础篇)
  • 解读爬虫中HTTP的秘密(高阶篇)

The data should be encrypted and transmitted to the server in case of mid-man attack. In our case, the OpenSSL and HTTPS

(3) Output Mechanism and UEFI Socket No-Mapping Error

  • Compile the Socket Test Program
build -p MdeModulePkg/MdeModulePkg.dsc -a X64 -b DEBUG -m RmtPkg/tcpsocket.inf -t GCC5

Error when building, which is caused by duplicate declaration in memecpy.c and sstd.h

 #pragma function(memcpy)
 ^
In file included from /home/hecmay/Desktop/Tiano/edk2/RmtPkg/memcpy.c:2:0:
/home/hecmay/Desktop/Tiano/edk2/sstdPkg/Include/sstd.h:13:56: error: expected declaration specifiers or ‘...’ before ‘(’ token
 #define memcpy(dest,source,count)  CopyMem(dest,source,(UINTN)(count))
                                                        ^
/home/hecmay/Desktop/Tiano/edk2/RmtPkg/memcpy.c:8:8: note: in expansion of macro ‘memcpy’
 void * memcpy ( void * dest, const void * source, size_t count)
        ^
cc1: all warnings being treated as errors
GNUmakefile:454: recipe for target '/home/hecmay/Desktop/Tiano/edk2/Build/MdeModule/DEBUG_GCC5/X64/RmtPkg/tcpsocket/OUTPUT/memcpy.obj' failed
make: *** [/home/hecmay/Desktop/Tiano/edk2/Build/MdeModule/DEBUG_GCC5/X64/RmtPkg/tcpsocket/OUTPUT/memcpy.obj] Error 1

we remove the declaration in memcpy.c and modify the declaration of Memcpy Function in sstd.h (replace UNITN with size_t). And the UEFI App can be launched successfully.

SOpen: Open '\TestSocket.efi' Success
[Security] 3rd party image[0] can be loaded after EndOfDxe: PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)/\TestSocket.efi.
InstallProtocolInterface: 5B1B31A1-9562-11D2-8E3F-00A0C969723B 3EC67040
Loading driver at 0x0003E125000 EntryPoint=0x0003E126BCB TestSocket.efi
InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 3EC5D698
ProtectUefiImageCommon - 0x3EC67040
  - 0x000000003E125000 - 0x0000000000002E40
InstallProtocolInterface: 752F3136-4E16-4FDC-A22A-E5F46812F4CA 3FE926D8
InstallProtocolInterface: 65530BC7-A359-410F-B010-5AADC7EC2B62 3EC673B8
InstallProtocolInterface: 41D94CD2-35B6-455A-8258-D4E51334AADD 3EC5CC20
InstallProtocolInterface: 09576E91-6D3F-11D2-8E39-00A0C969723B 3EC36D18
EmuVariablesUpdatedCallback
FSOpen: Open 'NvVars' Success
Saved NV Variables to NvVars file
Free the Received Buffer

Another problem is the output of Print function. Simply using Print("xxxxx %s\n", Str); just puts blank. The definition of Print in UEFI is like:

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第3张图片
UEFI Print Definition in BaseLib

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第4张图片
ShowBGRT
02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第5张图片
AsciiToUnicodeSize usage in BGRT.efi

Refer to the Usage in BGRT.efi. Converting the CHAR8 type to CHAR16 bit by bit within length.

static VOID
AsciiToUnicodeSize( CHAR8 *String, 
                    UINT8 length, 
                    CHAR16 *UniString)
{
    int len = length;
 
    while (*String != '\0' && len > 0) {
        *(UniString++) = (CHAR16) *(String++);
        len--;
    }
    *UniString = '\0';
}

After resolving the console output problem. The HTTP Request header and EFI_STATUS will be available for debugging. the EFI app failed to recognize the parameter passed in.

Result
  • EFI_STATUS Reference: http://wiki.phoenix.com/wiki/index.php/EFI_STATUS
02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第6张图片
iPXE Boot Stage
Debugging output

Some other errors when running the Socket Testing programms

# Error when staring image
[Security] 3rd party image[0] can be loaded after EndOfDxe: PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)/\hhh.efi.
InstallProtocolInterface: 5B1B31A1-9562-11D2-8E3F-00A0C969723B 3EC5A040
Loading driver at 0x0003E124000 EntryPoint=0x0003E124C42 TestSocket.efi
InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 3EC5B698
ProtectUefiImageCommon - 0x3EC5A040
  - 0x000000003E124000 - 0x00000000000031C0
InstallProtocolInterface: 752F3136-4E16-4FDC-A22A-E5F46812F4CA 3FE926D8
The Request Data: GET / HTTP/1.1
Host:10.192.13.99
Accept:* / *
Connection:Keep-Alive


InstallProtocolInterface: 65530BC7-A359-410F-B010-5AADC7EC2B62 3EC68E38
InstallProtocolInterface: 41D94CD2-35B6-455A-8258-D4E51334AADD 3EC5A6A0
InstallProtocolInterface: 09576E91-6D3F-11D2-8E39-00A0C969723B 3EC65798
EmuVariablesUpdatedCallback
FSOpen: Open 'NvVars' Success
Saved NV Variables to NvVars file
Config Sucess
 Connect Failure Code: 2
Error: Image at 0003E124000 start failed: Invalid Parameter
FSOpen: Open '\' Success
^[[25;01H^[[1m^[[33m^[[40mFS0:\> ^[[0m^[[37m^[[40mTcpRexmitTimeout: transmission timeout for TCB 3EC5A518
TcpRexmitTimeout: transmission timeout for TCB 3EC5A518
TcpRexmitTimeout: transmission timeout for TCB 3EC5A518
TcpRexmitTimeout: transmission timeout for TCB 3EC5A518
TcpConnectTimeout: connection closed because conenction timer timeout for TCB 3EC5A518
!!!! X64 Exception Type - 06(#UD - Invalid Opcode)  CPU Apic ID - 00000000 !!!!
RIP  - 000000003E1280A2, CS  - 0000000000000038, RFLAGS - 0000000000000282
RAX  - 00000000000000F8, RCX - 000000003EC68698, RDX - 000000003EC5A9C0
RBX  - 000000003FEB7901, RSP - 000000003FE92638, RBP - 0000000000000004
RSI  - 000000003FEBAE00, RDI - 000000003FEC7090
R8   - 000000003EC686E0, R9  - 000000003E7E5F96, R10 - 000000003FEACBE0
R11  - 00000000000003F8, R12 - 0000000000000080, R13 - 0000000000000008
R14  - 000000003FEBAD80, R15 - 000000003EC68698
DS   - 0000000000000030, ES  - 0000000000000030, FS  - 0000000000000030
GS   - 0000000000000030, SS  - 0000000000000030
CR0  - 0000000080010033, CR2 - 0000000000000000, CR3 - 000000003FC01000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 000000003FBEEA98 0000000000000047, LDTR - 0000000000000000
IDTR - 000000003F5CE018 0000000000000FFF,   TR - 0000000000000000
FXSAVE_STATE - 000000003FE92290
!!!! Find image based on IP(0x3E1280A2) /home/hecmay/Desktop/Tiano/edk2/Build/OvmfX64 \
/DEBUG_GCC5/X64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.dll \
(ImageBase=000000003E128000, EntryPoint=000000003E16D66C) !!!!

if run the same programme a second time. A different error is like:

# Tcp4Dispatcher. The station Addr and port could have been registered and occupied
# For details please see:
# MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dispatcher.c +407
Tcp4ConfigurePcb: Bind endpoint failed with Invalid Parameter
Config Error Code: 2
Connect0 Error Code: 19
Connect Failure Code: 19
Error: Image at 0003E124000 start failed: Not started

(4) Debugging on Socket for EFI

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第7张图片
Second try of Connecting

From the initial debugging trace, we found that the Tcp4DataConfig struct is set up correctly with data pushed in. However, it seems that the there is something wrong with the Event Triggering Mechanism.

EFI_STATUS Connect0(int sk)
{
    EFI_STATUS                           Status = EFI_NOT_FOUND;
    struct Socket* this = Socketfd[sk];
    if(this->m_pTcp4Protocol == NULL) {
        Print(L"The Socketfd is Null");
        return Status;
    }
    Status = this->m_pTcp4Protocol -> Connect(this->m_pTcp4Protocol, &this->ConnectToken);
    if(EFI_ERROR(Status)){
        Print(L"Connect0 Error Code: %d\n", Status);
        return Status;
    }
    UINTN index = 0;
    Status = gBS->WaitForEvent(1, &(this->ConnectToken.CompletionToken.Event), &index);
    Print(L"Wait Status: %d\n", Status);
    //SocketWait(this->ConnectToken.CompletionToken.Event);
    if( !EFI_ERROR(Status)){
        Status = this->ConnectToken.CompletionToken.Status;
        Print(L"Connect Success");
    }
    return Status;
}

So the Socket TCP/IP Connection was stopped before the Event could have been triggered. And this issue was initially originated from the calling of gBS->WaitforEvent Function

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第8张图片
Code block waiting for response from connection

Console Output

By referring to the UEFI Specification 2.7. The Event in struct EFI_TCP4_COMPLETION_TOKEN must be with EVT_NOTIFY_SIGNAL, but the gBS->WaitForEvent() function will return EFI

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第9张图片
Struct of EFI_TCP4_COMPLETION_TOKEN

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第10张图片
WaitForEvent return value

The Specification 2.7 says that EVT_NOTIFY_SIGNAL is not a event satisfying the wait condiftion


02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第11张图片
UEFI Spec page 173: WaitForEvent Description

So the possible solution is to change the type of triggered event. The previous wrong example is followed:

// Original WaitForEvent method 
Status = gBS->CreateEvent(EFI_NOTIFY_SIGNAL, TPL_CALLBACK, (EFI_EVENT_NOTIFY)SomeFunction, (VOID*)&this->ConnectToken, &this->ConnectToken.ComplectionToken.Event
// ....................................
UINTN index = 0;
Status = gBS->WaitForEvent(1, &this->ConnectToken.ComplectionToken.Event, &index);
// Then WaitForEvent will return EFI_INVALID_PARAMETER for it detects the event pointed by index is with type of EFI_NOTIFY_SIGNAL

After modification, we change the type pushed into WaitForEvent() from EFI_NOTIFY_SIGNAL to EFI_NOTIFY_WAIT:

VIOD myNotify(IN EFI_EVENT Event, IN VOID *Content){
     static UINTN times = 0;
     Print(L"The %d time to checkEvent \n", times);
     times++;
     EFI_STATUS Status = (EFI_STATUS)(*((EFI_STATUS *)(Content)))
     if (Status == EFI_SUCCESS) {
         gBS->SignalEvent(Event);
     } else {
         Print(L"CompletionToken Status %d\n", Status);
     }
}
//
// ......
//
EFI_STATUS Status = EFI_ABORTED;
UINTN index = 0;
EFI_EVENT myEvent;
Status = gBS->CreateEvent(EFI_NOTIFY_NOTIFY, TPL_NOTIFY, (EFI_EVENT_NOTIFY)myEventNotify, (VOID*)Content, &myEvent);
Status = gBS->WaitForEvent(1, &myEvent, &index);

// or we can use WaitForKey Event to realise the relay
Status = gBS->CreateEvent(EFI_TIMER | EFI_NOTIFY_SIGNAL, TPL_CALLBACK, (EFI_EVENT_NOTIFY)myEventNotify, (VOID*)Content, &myEvent);
Status = gBS->SetTimer(myEvent, TimerPeriodic, 10*1000*1000);
Status = gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &index);

With the previous type of Event, the output times variable will keep increasing. For the EFI_NOTIFY_WAIT Event, the status will be checked regularly and myEventNotify() will be triggered. And for EFI_NOTIFY_SIGNAL, the myEventNotify() will be triggered after the Event is signed as triggered.

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第12张图片
Output Example of nyEventNotify Function

Here we choose the latter one for relay function. Followed is the output of the TestSocket.efi, the two pieces of "Wait Status Code: 2" are caused by the same reason stated above:

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第13张图片
The Shortcut of Previous Version

The serial debugging log preview after changing the Event Type:

FSOpen: Open 'NvVars' Success
Saved NV Variables to NvVars file
Config Sucess Code: 0
[INFO] myEventNotify signal: 0
The Status is: 1054588512
Wait Status: 0
Connect Completion Success 0

Tranmitting now: 0
Wait Status: 0
Send Completion Success 0

Recving now: 0
Wait Status: 0
Recv Completion Success 0
The Recved Data: ???>
Free the Received Buffer
TcpSendIpPacket: No appropriate IpSender.
Tcp4Input: Discard a packet
FSOpen: Open '\' Success
TcpSendIpPacket: No appropriate IpSender.
Tcp4Input: Discard a packet

And we can also see detect the TCP connection on the server by using netstat to check the port occupation status continuously.

netstat -anp -c 2 | grep 80
# -a All | -n Numeric value but token  | -p Process | -c Continuously in frequency(s)
Netstat Command Results

To capture the communication packets in the UEFI Client and Server. we can use tcpdump to capture and explain the transmission data:

>>> sudo tcpdump -D  # Show all available network devices
...
>>> sudo tcpdump -X host ServerIP and ClientIP -vv -nn -w file
>>> # -x will print the transmission data and -vv is verbose mode
>>> # -nn means numeric value instead token
>>> # -w writes record to file; -r reads the file and reproduce the situation
Communication Between Server and UEFI Client

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第14张图片
The shortcut of details

(5) Concerns on the Reiveive() of TCP4_Protocol and Relevant Data structure

From the previous analysis, we consider the missing of Recv data caused by encoding incompatibility. Referring to the UEFI Spec 2.7:

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第15张图片
UEFI Spec 2.7 Page 1554

  • Also look into AppPkg/Applications/Socket and MdeMoudule/Universial/Network/SocketImpl.c for some intuition
  • Recommend to use Eclipse CDT for debugging usage
sudo apt-get install eclipse eclipse-cdt g++
# And then import the the existing folder into the Project panel
  • The Receive function is defined in Protocol/Tcp4.h, which is indeed is an instance of EFI_TCP4_RECEIVE Function
typedef
EFI_STATUS
(EFIAPI *EFI_TCP4_RECEIVE) (
  IN EFI_TCP4_PROTOCOL           *This,
  IN EFI_TCP4_IO_TOKEN           *Token
  );

(6) Pre-OS Machine Learning Based Malicious Operation Detection

In this part, we aim to design a Machine Learning based Malicious Operation Detection Framework on UEFI Pre-OS environment using embedded python.

It is really sufferable to use the built in UEFI Functions and Protocols. In this part, we are to use Python && Transplanted Standard C Library in UEFI Environment, which sound much more enjoyable -- the UEFI client will only undertake the task of transmitting the encrypted measurement value and log from TPM PCR with SSL.

  • Firewall Iptables Configuration on the Server
sudo iptables -A INPUT -p tcp -d 0/0 -s 0/0 --dport  8000 -j ACCEPT
sudo ufw allow 8000
service ufw status && service ufw enable
/etc/init.d/ufw restart
sudo netstat -ntlup | grep 8000

# Then telnet from client for testing purpose
telnet ServerIP Port
  • Socket [Error 98] Address Already in Use
    The time relay effect of four-way wavehand requires some more time before building up the next socket connection. Please see the resolution in the followed link.
    socket.error: [Errno 98] Address already in use

  • Std LibC Based Socket Client
    In this way, the UEFI Apps are prone to crush in QEMU... we may retry it on a UEFI environment of physical machine.

#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 

TestTcpSocket ( char * serverIP, int Port) {
    int rc;
    int sock;
    struct sockaddr_in v4;

    char data[1024];
    size_t sentBytes;
    size_t sendStrLen;

    if ( !((4 == sscanf (serverIP,
                    "%d.%d.%d.%d",
                    &Value1,
                    &Value2,
                    &Value3,
                    &Value4))
          && (Value1 <= 255)
          && (Value1 <= 255)
          && (Value1 <= 255)
          && (Value1 <= 255))){
        return -1;
    }

    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    ASSERT (sock != -1)

    memset(&v4, 0x00, sizeof(v4));

    v4.sin_len = sizeof(v4);
    v4.sin_family = AF_INET;
    v4.sin_addr.s_addr = Value1
                       | (Value2 << 8)
                       | (Value3 << 16)
                       | (Value4 << 24);
    v4.sin_port = htons(serverPort);
    rc = connect(sock, (struct sockaddr*)&v4, sizeof(v4));

//
// ......
//
}

Or we may merge the LibC based Socket program into OVMF (Since I consider the error was caused by the mapping problem.)

!!!! X64 Exception Type - 0D(#GP - General Protection)  CPU Apic ID - 00000000 !!!!
ExceptionData - 0000000000000000
RIP  - 000000003E0FC6E6, CS  - 0000000000000038, RFLAGS - 0000000000000282
RAX  - AFAFAFAF6C617470, RCX - 000000003FB21520, RDX - 000000003FEB6040
RBX  - 000000003FEBAF60, RSP - 000000003FE920D0, RBP - 000000003F5D1DA0
RSI  - 000000003FEBAE00, RDI - 000000003FEBAF60
R8   - 000000003EC22AE0, R9  - 00000000000000B8, R10 - 000000003EC190C0
R11  - 000000000000000C, R12 - 000000003FA0D598, R13 - 0000000000000008
R14  - 000000003FEBAD80, R15 - 000000003EC22A98
DS   - 0000000000000030, ES  - 0000000000000030, FS  - 0000000000000030
GS   - 0000000000000030, SS  - 0000000000000030
CR0  - 0000000080010033, CR2 - 0000000000000000, CR3 - 000000003FC01000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 000000003FBEEA98 0000000000000047, LDTR - 0000000000000000
IDTR - 000000003F5CE018 0000000000000FFF,   TR - 0000000000000000
FXSAVE_STATE - 000000003FE91D30
!!!! Find image based on IP(0x3E0FC6E6) /home/hecmay/Desktop/Tiano/edk2/Build/AppPkg/DEBUG_GCC5/X64/AppPkg/Applications/Sockets/DataSource/DataSource/DEBUG/DataSource.dll (ImageBase=000000003E0F6000, EntryPoint=000000003E1053AF) !!!!

The error -- General Protection Fault -- can be triggered by different factors. For details please see:
https://en.wikipedia.org/wiki/General_protection_fault

  • The Analysis of Remote Attestation Prerequisite
    UEFI TPM drivers will measure the event log and extend the TPM PCR value with it, and these sets of data will be important in process of implementation of remote attestation. Afterwards we are to extract the event log and pass it through to the server agent.
    02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第16张图片
    TPM based IMA

In the TcgPei driver, the data buffer will be measured, extended and logged in to the Event log list with a GUIDed HoB until DXE Stage:

// SecurityPkg/Tcg/TcgPei/TcgPei.c +252
/**
  Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
  and build a GUIDed HOB recording the event which will be passed to the DXE phase and
  added into the Event Log.

  @param[in]      PeiServices   Describes the list of possible PEI Services.
  @param[in]      HashData      Physical address of the start of the data buffer 
                                to be hashed, extended, and logged.
  @param[in]      HashDataLen   The length, in bytes, of the buffer referenced by HashData.
  @param[in]      NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.  
  @param[in]      NewEventData  Pointer to the new event data.  

  @retval EFI_SUCCESS           Operation completed successfully.
  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
  @retval EFI_DEVICE_ERROR      The command was unsuccessful.

**/
EFI_STATUS
HashLogExtendEvent (
  IN      EFI_PEI_SERVICES          **PeiServices,
  IN      UINT8                     *HashData,
  IN      UINTN                     HashDataLen,
  IN      TCG_PCR_EVENT_HDR         *NewEventHdr,
  IN      UINT8                     *NewEventData
  )
{

Later FvImage and CRTM Version etc will also be measured and extended in TPM PCR[0] (also to be passed into HoB and logged in DXE Stage)

The TPM Event Log Measuring mechanism in TcgDxe.c

typedef struct _TCG_DXE_DATA {
  EFI_TCG_PROTOCOL                  TcgProtocol;
  TCG_EFI_BOOT_SERVICE_CAPABILITY   BsCap;
  EFI_TCG_CLIENT_ACPI_TABLE         *TcgClientAcpiTable;
  EFI_TCG_SERVER_ACPI_TABLE         *TcgServerAcpiTable;
  UINTN                             EventLogSize;
  UINT8                             *LastEvent;
} TCG_DXE_DATA;

//
// ......
//

// mTcgDxeData -- the core struct of data storage in TPM DXE driver
TCG_DXE_DATA                 mTcgDxeData = {
  {
    TcgDxeStatusCheck,
    TcgDxeHashAll,
    TcgDxeLogEvent,
    TcgDxePassThroughToTpm,
    TcgDxeHashLogExtendEvent
  },
  {
    sizeof (mTcgDxeData.BsCap),
    { 1, 2, 0, 0 },
    { 1, 2, 0, 0 },
    1,
    TRUE,
    FALSE
  },
  &mTcgClientAcpiTemplate,
  &mTcgServerAcpiTemplate,
  0,
  NULL
};

Since EFI_TCG_PROTOCOL does not have the built-in function providing the capacity to retrieve Event log like EFI_TREE_PROTOCOL does, we need to extract the Event log separately with the TcgProtocol->StatusCheck() function.

  • Extracting Event Log from the EFI Event List Entry
    Please see the declaration of StatusCheck in EFI_TCG_PROTOCOL White Book

02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第17张图片
StatusCheck Declaration

Note that the TCGFeatureFlags is a reserved flag for TCG Protocol implementation. For details please see the Specification.

An example of the Event Log results:

Status = TcgProtocol->StatusCheck( TcgProtocol,
                                   &BootCapacity,
                                   &FeatureFlag,
                                   &LogLocation,
                                   &LogLastEntry);
LogAddress = LogLocation;
if (LogLocation != LogLastEntry) {
    do {
        Event = (TCG_PCR_EVENT *) LogAddress;
        PrintLog(Event, Verbose);
        LogAddress += sizeof(TCG_PCR_EVENT_HDR) + Event->EventSize;
    } while (LogAddress != LogLastEntry);
}

The Event Log is stored in the buffer in format of a list linked with pointers. The output of the event log and correspondent hash value:


02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework_第18张图片
Event Log of TPM Measurement
  • The Usage of CroptoPkg in UEFI Apps
    Since in real case, there is a possibility that the the data transmission be acquired and attacked by the malicious mid-man in the local area network, it is necessary to use OpenSSL to encrypt the value before transmission.

  • Test of SmmBackDoor Attack to the UEFI System
    After building up the framework, we are to test its effectiveness by injecting the system with a SMM backdoor. The github repository of the open source application:
    https://github.com/Cr4sh/SmmBackdoor

你可能感兴趣的:(02/14/2018 UEFI Remote Attestation based Malicious Operation Detection Framework)