狠狠撸

狠狠撸Share a Scribd company logo
Backdoor !!
vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方
2010/4/12
VTCライトニングトーク発表内容
しろやまたかゆき<shiro.t@gmail.com>
Hypercall とは?
l? ゲストOS からハイパーバイザを明示的に呼び出す方法
l? Binary Translation や VMEXIT/VMRESUME に比べコストが低い
l? 呼び出し方法が低コスト
l? ハイパーバイザに都合のいいデータのやり取りが可能
l? 準仮想化された OS で使用されている
l? Xen 対応の Linux カーネルなど
Xen での Hypercall の実装
l? 単純に int 命令でソフトウェア割り込みをかけているだけ
l? Ring0 の Xen hyper-visor が割り込みをキャッチし、指定のルーチンを
呼び出している
http://www.ylug.jp/download/hypercall_ylug_20061027.pdf
Hypercall は準仮想化だけのもの?
l? いえ、類似/同等の機能は完全仮想化のハイパーバイザにもあります!
l? 性能上の理由
l? Binary Translation や VMEXIT/VMRESUME に比べコストが低い
l? 仮想化ならではの機能の実現
l? VM間 / VM-Hypervisor 間の通信や制御 (VMCI)
例: VMCI
int a, s, len;
char buf[255];
struct sockaddr_vm addr = { 0 };
s = socket(PF_VSOCK_VMCI, SOCK_STREAM, 0);
addr.svm_family = AF_VSOCK_VMCI;
addr.svm_cid = VMADDR_CID_ANY;
addr.svm_rid = 2000;
bind(s, (struct sockaddr *) &addr, sizeofaddr);
listen(s, 5);
a = accept(s, (struct sockaddr *) &addr, &len);
len = recv(a, buf, sizeof buf, 0);
int a, s, len;
char *buf = “Hello, world!”;
struct sockaddr_vm addr = { 0 };
s = socket(PF_VSOCK_VMCI, SOCK_STREAM, 0);
addr.svm_family = AF_VSOCK_VMCI;
addr.svm_cid = GUEST2;
addr.svm_rid = 2000;
connect(s, (struct sockaddr *) &addr, sizeof addr);
len = send(s, buf, len, 0);
基本はソケットプログラミング
通常のPF_INETの代わりに
PF_VSOCK_VMCIに変更。
読み書き(send/recv)は変わらず
Hyper-?visor
Application
Guest ?OS
仮想マシン
Application
Guest ?OS
仮想マシン
Server
Client
ESX / Hyper-V の Hypercall
l? では、ESX / Hyper-V の Hypercall って どうやってるの?
ソースコードにきいてみよう!
VMware の場合: open-vm-tools
Open Virtual Machine Tools
l? vmware-tools のソースコードは公開されている (2007.9.4~)
l? Linux, FreeBSD, Solaris 用
l? vmsync など、標準の VMware Tools にないモジュールも存在
http://open-?vm-?tools.sourceforge.net/
Microsoft の場合
l? Hyper-V の統合サービス(Linux向け)のソースコードを公開!(2009.7.21)
l? これを読めば Hyper-V の hypercall も解明できる?
で、どうやってダウンロードすればいいの?
l? MS のサイトを漁りまわったけどソースコードを発見できず!!
l? 公開を報じる国内記事は多々あれど、ソースそのもののリンクはどこにもない
l? 駄目ぢゃん、っと思ってたら...
で、どうやってダウンロードすればいいの?
l? Linux-Kernel ML に Greg-KH 氏が投稿していた
l? パッチを 54 分割して...
l? 何とか苦労して取り出しました
l? 最近のカーネルソースには既に含まれている模様
ソースツリー: open-vm-tools の場合
l? open-vm-tools
l? 綺麗な階層構造、Makfile 完備
l? さまざまなOSでのビルドを前提としている
l? コード数、約24万行
- 「find –name ‘*.[ch]’ -print0 | xargs -0 wc –l 」の実行結果より
ソースツリー: open-vm-tools の場合
l? open-vm-tools の階層構造
+-?-? autom4te.cache/
+-?-? checkvm/
+-?-? config/
+-?-? docs/
+-?-? hgfsclient/
+-?-? hgfsmounter/
+-?-? lib/
+-?-? libguestlib/
+-?-? libvmtools/
+-?-? m4/
+-?-? modules/
| ? ? ?+-?-? freebsd/
| ? ? ?+-?-? linux/
| ? ? ?+-?-? solaris/
+-?-? rpctool/
+-?-? scripts/
+-?-? services/
| ? ? ?+-?-? plugins/
|| ? ? ?+-?-? vmtoolsd/
+-?-? tests/
+-?-? toolbox/
+-?-? vmblock-?fuse/
+-?-? vmware-?user/
+-?-? vmware-?user-?suid-?wrapper/
+-?-? xferlogs/ ?
| ? ? ?+-?-? linux/
| ? ? ?| ? ? ?+-?-? pvscsi/
| ? ? ?| ? ? ?+-?-? shared/
| ? ? ?| ? ? ?+-?-? vmblock/
| ? ? ?| ? ? ?+-?-? vmci/
| ? ? ?| ? ? ?+-?-? vmhgfs/
| ? ? ?| ? ? ?+-?-? vmmemctl/
| ? ? ?| ? ? ?+-?-? vmsync/
| ? ? ?| ? ? ?+-?-? vmxnet/
| ? ? ?| ? ? ?+-?-? vsock/
独自のツリー構造
多くのOSに対応
共通化モジュール、ユーザランドツール、
ドライバなど綺麗に分離されている
ソースツリー: Hyper-V の場合
l? linux integration component
l? linux-kernel に対するパッチで、Linux にべったりの構造
- カーネルパッチだけ?ユーザランドに何もない??
l? driver/staging/hv 以下に集中配置
l? 約2万行
ソースツリー: Hyper-V の場合
ファイル一覧
BlkVsc.c HvVpApi.h Vmbus.c
Channel.c Kconfig VmbusApi.h
Channel.h List.h VmbusChannelInterface.h
ChannelInterface.c Makefile VmbusPacketFormat.h
ChannelInterface.h Makefile.rej VmbusPrivate.h
ChannelMessages.h NetVsc.c blkvsc_drv.c
ChannelMgmt.c NetVsc.h hv.diff
ChannelMgmt.h NetVscApi.h logging.h
Connection.c RingBuffer.c netvsc_drv.c
Hv.c RingBuffer.h nvspprotocol.h
Hv.h RndisFilter.c osd.c
HvHalApi.h RndisFilter.h osd.h
HvHcApi.h Sources.c rndis.h
HvPtApi.h StorVsc.c storvsc_drv.c
HvStatus.h StorVscApi.h vmbus.h
HvSynicApi.h TODO vmbus_drv.c
HvTypes.h VersionInfo.h vstorage.h
Linux への侵食方法:VMware の場合
あくまで「物理デバイスに対するドライバ」の立場
l? VMware-tools の有無に関わらず、仮想デバイスが存在する前提
l? PCIバス上にデバイスがつながっているように見える
l? PCIバスのデバイス検出手順に従い、ドライバがロードされていく
l? VendorID: 0x15AD で、指定
の DeviceID をもつドライバが
選定される
l? 選定されたドライバのprobe 関数を
実行して、本当に対応するデバイスか
を確認させる
l? 失敗が帰ったら、次の候補となる
ドライバを探す
/* Our own PCI IDs
* VMware SVGA II (Unified VGA)
* VMware SVGA (PCI Accelerator)
* VMware vmxnet (Idealized NIC)
* VMware vmxscsi (Abortive idealized SCSI controller)
* VMware chipset (Subsystem ID for our motherboards)
* VMware e1000 (Subsystem ID)
* VMware vmxnet3 (Uniform Pass Through NIC)
*/
#define PCI_VENDOR_ID_VMWARE 0x15AD
#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405
#define PCI_DEVICE_ID_VMWARE_SVGA 0x0710
#define PCI_DEVICE_ID_VMWARE_NET 0x0720
#define PCI_DEVICE_ID_VMWARE_SCSI 0x0730
#define PCI_DEVICE_ID_VMWARE_VMCI 0x0740
#define PCI_DEVICE_ID_VMWARE_CHIPSET 0x1976
#define PCI_DEVICE_ID_VMWARE_82545EM 0x0750 /* single port */
#define PCI_DEVICE_ID_VMWARE_82546EB 0x0760 /* dual port */
#define PCI_DEVICE_ID_VMWARE_EHCI 0x0770
#define PCI_DEVICE_ID_VMWARE_UHCI 0x0774
#define PCI_DEVICE_ID_VMWARE_XHCI 0x0778
#define PCI_DEVICE_ID_VMWARE_1394 0x0780
#define PCI_DEVICE_ID_VMWARE_BRIDGE 0x0790
#define PCI_DEVICE_ID_VMWARE_ROOTPORT 0x07A0
#define PCI_DEVICE_ID_VMWARE_VMXNET3 0x07B0
#define PCI_DEVICE_ID_VMWARE_VMXWIFI 0x07B8
#define PCI_DEVICE_ID_VMWARE_PVSCSI 0x07C0
#define PCI_DEVICE_ID_VMWARE_82574 0x07D0
lib/include/vm_device_version.h ?より
Linux への侵食方法:VMware の場合
余談: vmxnet の Morphing
l? ESX 2.x では、vlance と vmxnet は区別されてました
l? vlance vendorID: 0x1022(AMD) deviceID: 0x2000
l? vmxnet vendorID: 0x15AD(VMware) deviceID: 0x0720
l? ESX 3.x 以降で、vlance -> vmxnet の入れ替えしました?
Linux への侵食方法:VMware の場合
余談: vmxnet の Morphing
l? ESX 3.x 以降の vlance は、vmxnet を「兼用」している
l? たまたま、AMD-PCNET が 32byte しか IO空間を使ってなかった点を利用
l? 64byte まで取れるIO空間の後ろ32byte に vmxnet の IO空間を追加
/*
* Since this is a vlance adapter we can only use it if
* its I/0 space is big enough for the adapter to be
* capable of morphing. This is the first requirement
* for this adapter to potentially be morphable. The
* layout of a morphable LANCE adapter is
*
* I/O space:
*
* |------------------|
* | LANCE IO PORTS |
* |------------------|
* | MORPH PORT |
* |------------------|
* | VMXNET IO PORTS |
* |------------------|
*
* VLance has 8 ports of size 4 bytes, the morph port is 4 bytes, and
* Vmxnet has 10 ports of size 4 bytes.
*
* We shift up the ioaddr with the size of the LANCE I/O space since
* we want to access the vmxnet ports. We also shift the ioaddr up by
* the MORPH_PORT_SIZE so other port access can be independent of
* whether we are Vmxnet or a morphed VLance. This means that when
* we want to access the MORPH port we need to subtract the size
* from ioaddr to get to it.
*/
Linux への侵食方法:VMware の場合
余談: vmxnet の Morphing
l? vmxnet ドライバの probe 関数(vmxnet_probe_device)の挙動
l? PCI の Vendor ID を取得
- 0x15AD (VMware) なら、そのまま vmxnet デバイスと判断
? 旧 vmxnet との互換性の確保
- 0x1022 (AMD) の場合
? IO空間のサイズを取得し、64byte とサイズを比較
? それより小さかったら? 「うちの子じゃない」 で probe に失敗を返す
? 64byte 以上なら、「うちの子だから」と認定
? morph port に outw で値を書き込み、vmxnet として振舞わせる
Linux への侵食方法:VMware の場合
static int
vmxnet_morph_device(unsigned int morphAddr) // IN
{
uint16 magic;
/* Read morph port to verify that we can morph the adapter. */
magic = inw(morphAddr);
if (magic != LANCE_CHIP && magic != VMXNET_CHIP) {
printk(KERN_ERR "Invalid magic, read: 0x%08X?n", magic);
return -1;
}
/* Morph adapter. */
outw(VMXNET_CHIP, morphAddr);
/* Verify that we morphed correctly. */
magic = inw(morphAddr);
if (magic != VMXNET_CHIP) {
printk(KERN_ERR "Couldn't morph adapter. Invalid magic, read: 0x%08X?n",
magic);
goto morph_back;
}
return 0;
morph_back:
/* Morph back to LANCE hw. */
outw(LANCE_CHIP, morphAddr);
return -1;
}
VMM
Linux への侵食方法:VMware の場合
l? あくまで正規のデバイスドライバとしてロードされる
l? 比較的、物理デバイスに近いエミュレーションがなされている
l? Backdoor を使ってデバイスエミュレーションをある程度「バイパス」する
Linux ?kernel
vmxnet_drv VGA LSILogic
NIC VGA SCSI
VendorID: ?xxxx
DeviceID ?: ?xxxx
VendorID: ?xxxx
DeviceID ?: ?xxxx
VendorID: ?xxxx
DeviceID ?: ?xxxx
PCI ?バス Backdoor
vmsync
vmUser
vmmemctl
VMkernel
vmtools ? 提供ドライバ
ネイティブドライバ
Backdoor : IO空間の in/out 命令
l? VMware の Backdoor は、指定のIO空間への in /out 命令
l? in / out : x86 のもつ IO 空間へのデータの読み書きの命令
l? NICなどの一般的なデバイスは IO空間の一部を通じてデータをやり取りする
- グラフィックカードなどのより大きな空間を必要とするものは、メモリ空間
にマップされる
- PCI は IO空間 / メモリマップのどちらの方法もサポートする
l? VMware ではこの in / out 命令を転用している
l? 詳細: http://chitchat.at.infoseek.co.jp/vmware/backdoorj.html
Backdoor : IO空間の in/out 命令
static ?void
BalloonTimerHandler(void ?*clientData) ?// ?IN
{
Balloon ?*b ?= ?(Balloon ?*) ?clientData;?
uint32 ?target ?= ?0;? ?// ?Silence ?compiler ?warning.
int ?status;?
/* ?update ?stats ?*/
STATS_INC(b-?>stats.timer);?
/* ?reset, ?if ?specified ?*/
if ?(b-?>resetFlag) ?{
BalloonReset(b);?
}
/* ?contact ?monitor ?via ?backdoor ?*/
status ?= ?BalloonMonitorGetTarget(b, ?&target);?
/* ?decrement ?slowPageAllocationCycles ?counter ?*/
if ?(b-?>slowPageAllocationCycles ?> ?0) ?{
b-?>slowPageAllocationCycles-?-?;?
}
if ?(status ?== ?BALLOON_SUCCESS) ?{
/* ?update ?target, ?adjust ?size ?*/
b-?>nPagesTarget ?= ?target;?
(void) ?BalloonAdjustSize(b, ?target);?
}
}
Backdoor : IO空間の in/out 命令
static ?void
BalloonTimerHandler(void ?*clientData) ?// ?IN
{
Balloon ?*b ?= ?(Balloon ?*) ?clientData;?
uint32 ?target ?= ?0;? ?// ?Silence ?compiler ?warning.
int ?status;?
/* ?update ?stats ?*/
STATS_INC(b-?>stats.timer);?
/* ?reset, ?if ?specified ?*/
if ?(b-?>resetFlag) ?{
BalloonReset(b);?
}
/* ?contact ?monitor ?via ?backdoor ?*/
status ?= ?BalloonMonitorGetTarget(b, ?&target);?
/* ?decrement ?slowPageAllocationCycles ?counter ?*/
if ?(b-?>slowPageAllocationCycles ?> ?0) ?{
b-?>slowPageAllocationCycles-?-?;?
}
if ?(status ?== ?BALLOON_SUCCESS) ?{
/* ?update ?target, ?adjust ?size ?*/
b-?>nPagesTarget ?= ?target;?
(void) ?BalloonAdjustSize(b, ?target);?
}
}
static ?int
BalloonMonitorGetTarget(Balloon ?*b, ? ? ? ? ?// ?IN
uint32 ?*target) ?// ?OUT
{
Backdoor_proto ?bp;?
unsigned ?long ?limit;?
uint32 ?limit32;?
uint32 ?status;?
limit ?= ?OS_ReservedPageGetLimit();?
/* ?Ensure ?limit ?fits ?in ?32-?bits ?*/
limit32 ?= ?(uint32)limit;?
if ?(limit32 ?!= ?limit) ?{
return ?BALLOON_FAILURE;?
}
/* ?prepare ?backdoor ?args ?*/
bp.in.cx.halfs.low ?= ?BALLOON_BDOOR_CMD_TARGET;?
bp.in.size ?= ?limit;?
/* ?invoke ?backdoor ?*/
Backdoor_Balloon(&bp);?
/* ?parse ?return ?values ?*/
status ? ?= ?bp.out.ax.word;?
*target ?= ?bp.out.bx.word;?
Backdoor : IO空間の in/out 命令
static ?void
BalloonTimerHandler(void ?*clientData) ?// ?IN
{
Balloon ?*b ?= ?(Balloon ?*) ?clientData;?
uint32 ?target ?= ?0;? ?// ?Silence ?compiler ?warning.
int ?status;?
/* ?update ?stats ?*/
STATS_INC(b-?>stats.timer);?
/* ?reset, ?if ?specified ?*/
if ?(b-?>resetFlag) ?{
BalloonReset(b);?
}
/* ?contact ?monitor ?via ?backdoor ?*/
status ?= ?BalloonMonitorGetTarget(b, ?&target);?
/* ?decrement ?slowPageAllocationCycles ?counter ?*/
if ?(b-?>slowPageAllocationCycles ?> ?0) ?{
b-?>slowPageAllocationCycles-?-?;?
}
if ?(status ?== ?BALLOON_SUCCESS) ?{
/* ?update ?target, ?adjust ?size ?*/
b-?>nPagesTarget ?= ?target;?
(void) ?BalloonAdjustSize(b, ?target);?
}
}
static ?int
BalloonMonitorGetTarget(Balloon ?*b, ? ? ? ? ?// ?IN
uint32 ?*target) ?// ?OUT
{
Backdoor_proto ?bp;?
unsigned ?long ?limit;?
uint32 ?limit32;?
uint32 ?status;?
limit ?= ?OS_ReservedPageGetLimit();?
/* ?Ensure ?limit ?fits ?in ?32-?bits ?*/
limit32 ?= ?(uint32)limit;?
if ?(limit32 ?!= ?limit) ?{
return ?BALLOON_FAILURE;?
}
/* ?prepare ?backdoor ?args ?*/
bp.in.cx.halfs.low ?= ?BALLOON_BDOOR_CMD_TARGET;?
bp.in.size ?= ?limit;?
/* ?invoke ?backdoor ?*/
Backdoor_Balloon(&bp);?
/* ?parse ?return ?values ?*/
status ? ?= ?bp.out.ax.word;?
*target ?= ?bp.out.bx.word;?
static ?INLINE
void ?Backdoor_Balloon(Backdoor_proto ?*myBp) ?{
myBp-?>in.ax.word ?= ?BALLOON_BDOOR_MAGIC;?
myBp-?>in.dx.halfs.low ?= ?BALLOON_BDOOR_PORT;?
Backdoor_InOut(myBp);?
}
Backdoor : IO空間の in/out 命令
Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT
{
uint32 dummy;
__asm__ __volatile__(
#ifdef __PIC__
"pushl %%ebx" "?n?t"
#endif
"pushl %%eax" "?n?t"
"movl 20(%%eax), %%edi" "?n?t"
"movl 16(%%eax), %%esi" "?n?t"
"movl 12(%%eax), %%edx" "?n?t"
"movl 8(%%eax), %%ecx" "?n?t"
"movl 4(%%eax), %%ebx" "?n?t"
"movl (%%eax), %%eax" "?n?t"
"inl %%dx, %%eax" "?n?t"
"xchgl %%eax, (%%esp)" "?n?t"
"movl %%edi, 20(%%eax)" "?n?t"
"movl %%esi, 16(%%eax)" "?n?t"
"movl %%edx, 12(%%eax)" "?n?t"
"movl %%ecx, 8(%%eax)" "?n?t"
"movl %%ebx, 4(%%eax)" "?n?t"
"popl (%%eax)" "?n?t"
#ifdef __PIC__
"popl %%ebx" "?n?t"
#endif
: "=a" (dummy)
: "0" (myBp)
/*
* vmware can modify the whole VM state without the compiler knowing
* it. So far it does not modify EFLAGS. --hpreg
*/
:
#ifndef __PIC__
"ebx",
#endif
"ecx", "edx", "esi", "edi", "memory"
);
}
この inl 命令の実行した瞬間に
VMkernel 側に処理が渡り、該当する
機能が実行され、結果が vCPU の
EAX 、ECX 、 EDX 、 ESI、EDI レジスタ
に書き込まれる
Hyper-V のドライバイメージ
l? Hyper-V の場合は、デバイスではなく「バス」を追加している
l? PCI バスの下に、なんかバスがある...
l? なんかバスが「外」に伸びてるっぽい...
VMM
Linux ?kernel
レガシNIC VGA IDE
VendorID: ?xxxx
DeviceID ?: ?xxxx
VendorID: ?xxxx
DeviceID ?: ?xxxx
VendorID: ?xxxx
DeviceID ?: ?xxxx
PCI ?バス
ネイティブドライバ
21140 VGA IDE
VMBUS
Backdoor
vmbus_drv
netvsc_drv storage_drv
NIC SCSI
Hyper-?V
ParentVM
Hyper-V のドライバイメージ
l? Hyper-V の場合は、デバイスではなく「バス」を追加している
l? PCI バスの下に、なんかバスがある...
l? なんかバスが「外」に伸びてるっぽい...
Linux の侵食方法 : Hyper-V の場合
l? とにかく vmbus_drv デバイスドライバをロードする
l? VMBUS という何らかの「バス」があると Linux に誤認させる
l? VMBUS も、PCI と同じようにバス上のノードの検出を行う
- VendorID と Device ID ではなく、ClassID という GUID で識別
- ノードごと、netvsc_drv, storagevsc_drv, blkvsc_drv がロードされる
? VSC : Virtualization Service Client の略
l? 各 VSC はデバイスドライバだが、その下にはエミュレーションされたデバイス
はまったく存在しない!!
Linux の侵食方法 : Hyper-V の場合
http://enterprise.watch.impress.co.jp/cda/parts/image_for_link/41502-?13748-?4-?1.html
本当にこの通りでした...
Linux の侵食方法 : Hyper-V の場合
もう少し詳しい 階層構造
l? 大きく4層に分かれる
l? *_drv : Linux のデバイスドライバ(カーネルモジュール)としての体裁を整える
l? Vsc, Vmbus : 各ドライバの実態となる実装
l? Channel, Connection : VMBUS の通信機能の実装
l? osd : メモリ確保など
OS機能の抽象化
l? Hv : Hyper-V との
実際のインターフェイス
Linux ?kernel
osd
VMM
Vmbus
vmbus_drvstoragevsc_drvnetvsc_drv blcvsc_drv
Hv
Channel
Connection
Channel ?Mgmt
StorVscNetVsc BlcVsc
Linux ?Kernel ?とのインターフェイス
ドライバー中心部分
VMBUS ?通信機能
Backdoor : そのメモリに触ると...
Hyper-V のバックドアは特定のメモリアドレス
l? Hv はロードされると以下の振る舞いをする
l? CPUID 命令を実行し、Hyper-V の上かを確認する
- CPUID(1) の ECXの31bit 目を確認
l? 続けて CPUID 命令を実行し、ハイパーバイザのベンダー(!)や
バージョンを取得する
l? メモリを1ページ確保する
- これは通常の valloc が使用され、実行時により異なるページが
割り当てられる
l? wmsr でそのメモリの物理アドレスを vCPU に書き込む(!)
- MSR: Model Specific Register
? PentiumPro 以降のCPUにある、製品独自の設定を保存したり、
プロファイリング用のカウンタとなるレジスタ
? 詳細: http://mcn.oops.jp/wiki/index.php?CPU%2FCPUID%2FMSR
l? 以降、Hypercall はこのメモリへのアクセスすると、Hypercall が発生する
Backdoor : Hv初期化部分、Hyper-V 上かを確認
Name:
HvQueryHypervisorPresence()
Description:
Query the cpuid for presense of windows hypervisor
--*/
static int
HvQueryHypervisorPresence (
void
)
{
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
unsigned int op;
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
op = HvCpuIdFunctionVersionAndFeatures;
do_cpuid(op, &eax, &ebx, &ecx, &edx);
return (ecx & HV_PRESENT_BIT);
}
Backdoor : Hv初期化部分、Hyper-V 上かを確認
Name:
HvQueryHypervisorPresence()
Description:
Query the cpuid for presense of windows hypervisor
--*/
static int
HvQueryHypervisorPresence (
void
)
{
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
unsigned int op;
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
op = HvCpuIdFunctionVersionAndFeatures;
do_cpuid(op, &eax, &ebx, &ecx, &edx);
return (ecx & HV_PRESENT_BIT);
}
typedef enum _HV_CPUID_FUNCTION
{
HvCpuIdFunctionVersionAndFeatures = 0x00000001,
HvCpuIdFunctionHvVendorAndMaxFunction = 0x40000000,
HvCpuIdFunctionHvInterface = 0x40000001,
//
// The remaining functions depend on the value of HvCpuIdFunctionInterface
//
HvCpuIdFunctionMsHvVersion = 0x40000002,
HvCpuIdFunctionMsHvFeatures = 0x40000003,
HvCpuIdFunctionMsHvEnlightenmentInformation = 0x40000004,
HvCpuIdFunctionMsHvImplementationLimits = 0x40000005
} HV_CPUID_FUNCTION, *PHV_CPUID_FUNCTION;
Backdoor : Hv初期化部分、Hyper-V 上かを確認
Name:
HvQueryHypervisorPresence()
Description:
Query the cpuid for presense of windows hypervisor
--*/
static int
HvQueryHypervisorPresence (
void
)
{
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
unsigned int op;
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
op = HvCpuIdFunctionVersionAndFeatures;
do_cpuid(op, &eax, &ebx, &ecx, &edx);
return (ecx & HV_PRESENT_BIT);
}
static inline void do_cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
unsigned int *edx)
{
__asm__ __volatile__("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (op),
"c" (ecx));
}
Backdoor : Hv初期化部分、Hyper-V 上かを確認
Name:
HvQueryHypervisorPresence()
Description:
Query the cpuid for presense of windows hypervisor
--*/
static int
HvQueryHypervisorPresence (
void
)
{
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
unsigned int op;
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
op = HvCpuIdFunctionVersionAndFeatures;
do_cpuid(op, &eax, &ebx, &ecx, &edx);
return (ecx & HV_PRESENT_BIT);
}
//
// #defines
//
#define HV_PRESENT_BIT 0x80000000
Backdoor : Hv初期化部分、Hyper-V 上かを確認
Hyper-V 上の仮想マシンでの
CPUID 。確かに ECX の31bit目が
立っている
ESX上の仮想マシン
31bit 目は立っていない
0x8C082201
0x80000000
0x80000000
OR
0x00080201
0x80000000
0x00000000
OR
Backdoor : Hv初期化部分、アクセス用のアドレスを設定
if ?(gHvContext.GuestId ?== ?HV_LINUX_GUEST_ID)
{
// ?Allocate ?the ?hypercall ?page ?memory
//virtAddr ?= ?PageAlloc(1);?
virtAddr ?= ?VirtualAllocExec(PAGE_SIZE);?
if ?(!virtAddr)
{
DPRINT_ERR(VMBUS, ?"unable ?to ?allocate ?hypercall ?page!!");?
goto ?Cleanup;?
}
hypercallMsr.Enable ?= ?1;?
//hypercallMsr.GuestPhysicalAddress ?= ?Logical2PhysicalAddr(virtAddr) ?>> ?PAGE_SHIFT;?
hypercallMsr.GuestPhysicalAddress ?= ?Virtual2Physical(virtAddr) ?>> ?PAGE_SHIFT;?
WriteMsr(HV_X64_MSR_HYPERCALL, ?hypercallMsr.AsUINT64);?
// ?Confirm ?that ?hypercall ?page ?did ?get ?setup.
hypercallMsr.AsUINT64 ?= ?0;?
hypercallMsr.AsUINT64 ?= ?ReadMsr(HV_X64_MSR_HYPERCALL);?
if ?(!hypercallMsr.Enable)
{
DPRINT_ERR(VMBUS, ?"unable ?to ?set ?hypercall ?page!!");?
goto ?Cleanup;?
}
gHvContext.HypercallPage ?= ?virtAddr;?
osd.c にて定義。単に __valloc を
呼び出しているのみ。
単なるメモリ確保のため、どのアドレスが
変えるかは実行依存の模様
仮想アドレスを物理アドレスに書き換えた後、
CPU の MSR レジスタにアドレスを書き込む
Backdoor : Hypercall の実際
static u64
HvDoHypercall (
u64 Control,
void* Input,
void* Output
)
{
#ifdef CONFIG_X86_64
u64 hvStatus=0;
u64 inputAddress = (Input)? GetPhysicalAddress(Input) : 0;
u64 outputAddress = (Output)? GetPhysicalAddress(Output) : 0;
volatile void* hypercallPage = gHvContext.HypercallPage;
DPRINT_DBG(VMBUS, "Hypercall <control %llx input phys %llx virt %p output phys %llx virt %p hypercall %p>",
Control,
inputAddress,
Input,
outputAddress,
Output,
hypercallPage);
__asm__ __volatile__ ("mov %0, %%r8" : : "r" (outputAddress): "r8");
__asm__ __volatile__ ("call *%3" : "=a"(hvStatus): "c" (Control), "d" (inputAddress), "m" (hypercallPage));
DPRINT_DBG(VMBUS, "Hypercall <return %llx>", hvStatus);
return hvStatus;
RCXに命令コードを、RDX に入力データのアドレスを
突っ込んだ後、hypercallPage に call でジャンプし、
Hypercall を行っている (コールゲート?)
Backdoor : そのメモリに触ると...
l? 割り込み、どうするのん?
l? VMware の場合、各デバイスは PCI 上のデバイスのため、PCIバスを通じて
個々のデバイスが (ゲスト)OSへ 割り込みをかけることができた
- = VMM 側からゲストOSにデータを投げることができた
l? Hyper-V の場合は?
l? Linux Intergrated Module では、 IRQ 5 を VMBUS の割り込みとして使用
余談: なぜ、Hyper-V の起動ディスクは IDE only なのか
l? VMBUS がないと統合モジュールが動かないため
l? OS ロード前は、VMBUS などというバスを認識できない
l? そもそも 仮想マシンの上の BIOS レベルで VMBUS ドライバを実装する必要
l? OS ロード後なら、追加的に VMBUS をロードできる
まとめ
l? 同じハイパーバイザ型の 仮想化ソフトウェアでも、Hypercall の
方法は各社各様
l? 意外ときっちり実装している ESX の VMM
l? vmxnet ドライバも割と普通に IO 処理を行っている
l? 物理とは大きく異なる Hyper-V の VMM
l? エミュレートされたデバイスとは別に、本当に架空のデバイスを生成
l? VMBUS という架空のバスを通じて架空のデバイスを接続
l? 原理的に、morphing はできない。
- エミュレートデバイスと架空のデバイスは永久に混在する見込み

More Related Content

What's hot (20)

Socket tcp ip client server on langace c Socket tcp ip client server on langace c
Socket tcp ip client server on langace c
mouad Lousimi
?
???? ?? ?? ???
???? ?? ?? ??????? ?? ?? ???
???? ?? ?? ???
GeunCheolYeom
?
OVN 設定サンプル | OVN config example 2015/12/27
OVN 設定サンプル | OVN config example 2015/12/27OVN 設定サンプル | OVN config example 2015/12/27
OVN 設定サンプル | OVN config example 2015/12/27
Kentaro Ebisawa
?
vSRX on Your Laptop : PCで始めるvSRX ~JUNOSをさわってみよう!~
vSRX on Your Laptop : PCで始めるvSRX ~JUNOSをさわってみよう!~vSRX on Your Laptop : PCで始めるvSRX ~JUNOSをさわってみよう!~
vSRX on Your Laptop : PCで始めるvSRX ~JUNOSをさわってみよう!~
Juniper Networks (日本)
?
ML2/OVN アーキテクチャ概観
ML2/OVN アーキテクチャ概観ML2/OVN アーキテクチャ概観
ML2/OVN アーキテクチャ概観
Yamato Tanaka
?
ストレージネットワーク基础讲座
ストレージネットワーク基础讲座ストレージネットワーク基础讲座
ストレージネットワーク基础讲座
Brocade
?
Alphorm.com Support de la Formation VMware vSphere 6, Les machines virtuellesAlphorm.com Support de la Formation VMware vSphere 6, Les machines virtuelles
Alphorm.com Support de la Formation VMware vSphere 6, Les machines virtuelles
Alphorm
?
IOS/IOS-XE 運用管理機能アップデート
IOS/IOS-XE 運用管理機能アップデートIOS/IOS-XE 運用管理機能アップデート
IOS/IOS-XE 運用管理機能アップデート
シスコシステムズ合同会社
?
20180706冲痴虫搁补颈濒颁颁冲ワークショップ编冲狈奥
20180706冲痴虫搁补颈濒颁颁冲ワークショップ编冲狈奥20180706冲痴虫搁补颈濒颁颁冲ワークショップ编冲狈奥
20180706冲痴虫搁补颈濒颁颁冲ワークショップ编冲狈奥
VxRail ChampionClub
?
alphorm.com - Formation VMware vSphere 5alphorm.com - Formation VMware vSphere 5
alphorm.com - Formation VMware vSphere 5
Alphorm
?
Zabbix最新情報 ~Zabbix 6.0に向けて~ @OSC2021 Online/Fall
Zabbix最新情報 ~Zabbix 6.0に向けて~ @OSC2021 Online/FallZabbix最新情報 ~Zabbix 6.0に向けて~ @OSC2021 Online/Fall
Zabbix最新情報 ~Zabbix 6.0に向けて~ @OSC2021 Online/Fall
Atsushi Tanaka
?
2011年度 新3年生向け
2011年度 新3年生向け2011年度 新3年生向け
2011年度 新3年生向け
Yuki Takahashi
?
鲍贰贵滨时代のブートローダ
鲍贰贵滨时代のブートローダ鲍贰贵滨时代のブートローダ
鲍贰贵滨时代のブートローダ
Takuya ASADA
?
Interrupt Affinityについて
Interrupt AffinityについてInterrupt Affinityについて
Interrupt Affinityについて
Takuya ASADA
?
Linux KVMではじめるカンタン仮想化入門
Linux KVMではじめるカンタン仮想化入門Linux KVMではじめるカンタン仮想化入門
Linux KVMではじめるカンタン仮想化入門
VirtualTech Japan Inc.
?
Mise en place d'un système de messagerie sous debian avec: postfix, dovecot, ...Mise en place d'un système de messagerie sous debian avec: postfix, dovecot, ...
Mise en place d'un système de messagerie sous debian avec: postfix, dovecot, ...
Manassé Achim kpaya
?
Alphorm.com Formation VirtualBoxAlphorm.com Formation VirtualBox
Alphorm.com Formation VirtualBox
Alphorm
?
“見てわかる” ファイバーチャネルSAN基礎講座(第2弾)~FC SAN設計における勘所とは?~
“見てわかる” ファイバーチャネルSAN基礎講座(第2弾)~FC SAN設計における勘所とは?~“見てわかる” ファイバーチャネルSAN基礎講座(第2弾)~FC SAN設計における勘所とは?~
“見てわかる” ファイバーチャネルSAN基礎講座(第2弾)~FC SAN設計における勘所とは?~
Brocade
?
VMware vSphere
VMware vSphereVMware vSphere
VMware vSphere
零壹科技股份有限公司
?
Socket tcp ip client server on langace c Socket tcp ip client server on langace c
Socket tcp ip client server on langace c
mouad Lousimi
?
OVN 設定サンプル | OVN config example 2015/12/27
OVN 設定サンプル | OVN config example 2015/12/27OVN 設定サンプル | OVN config example 2015/12/27
OVN 設定サンプル | OVN config example 2015/12/27
Kentaro Ebisawa
?
vSRX on Your Laptop : PCで始めるvSRX ~JUNOSをさわってみよう!~
vSRX on Your Laptop : PCで始めるvSRX ~JUNOSをさわってみよう!~vSRX on Your Laptop : PCで始めるvSRX ~JUNOSをさわってみよう!~
vSRX on Your Laptop : PCで始めるvSRX ~JUNOSをさわってみよう!~
Juniper Networks (日本)
?
ML2/OVN アーキテクチャ概観
ML2/OVN アーキテクチャ概観ML2/OVN アーキテクチャ概観
ML2/OVN アーキテクチャ概観
Yamato Tanaka
?
ストレージネットワーク基础讲座
ストレージネットワーク基础讲座ストレージネットワーク基础讲座
ストレージネットワーク基础讲座
Brocade
?
Alphorm.com Support de la Formation VMware vSphere 6, Les machines virtuellesAlphorm.com Support de la Formation VMware vSphere 6, Les machines virtuelles
Alphorm.com Support de la Formation VMware vSphere 6, Les machines virtuelles
Alphorm
?
20180706冲痴虫搁补颈濒颁颁冲ワークショップ编冲狈奥
20180706冲痴虫搁补颈濒颁颁冲ワークショップ编冲狈奥20180706冲痴虫搁补颈濒颁颁冲ワークショップ编冲狈奥
20180706冲痴虫搁补颈濒颁颁冲ワークショップ编冲狈奥
VxRail ChampionClub
?
alphorm.com - Formation VMware vSphere 5alphorm.com - Formation VMware vSphere 5
alphorm.com - Formation VMware vSphere 5
Alphorm
?
Zabbix最新情報 ~Zabbix 6.0に向けて~ @OSC2021 Online/Fall
Zabbix最新情報 ~Zabbix 6.0に向けて~ @OSC2021 Online/FallZabbix最新情報 ~Zabbix 6.0に向けて~ @OSC2021 Online/Fall
Zabbix最新情報 ~Zabbix 6.0に向けて~ @OSC2021 Online/Fall
Atsushi Tanaka
?
2011年度 新3年生向け
2011年度 新3年生向け2011年度 新3年生向け
2011年度 新3年生向け
Yuki Takahashi
?
鲍贰贵滨时代のブートローダ
鲍贰贵滨时代のブートローダ鲍贰贵滨时代のブートローダ
鲍贰贵滨时代のブートローダ
Takuya ASADA
?
Interrupt Affinityについて
Interrupt AffinityについてInterrupt Affinityについて
Interrupt Affinityについて
Takuya ASADA
?
Linux KVMではじめるカンタン仮想化入門
Linux KVMではじめるカンタン仮想化入門Linux KVMではじめるカンタン仮想化入門
Linux KVMではじめるカンタン仮想化入門
VirtualTech Japan Inc.
?
Mise en place d'un système de messagerie sous debian avec: postfix, dovecot, ...Mise en place d'un système de messagerie sous debian avec: postfix, dovecot, ...
Mise en place d'un système de messagerie sous debian avec: postfix, dovecot, ...
Manassé Achim kpaya
?
Alphorm.com Formation VirtualBoxAlphorm.com Formation VirtualBox
Alphorm.com Formation VirtualBox
Alphorm
?
“見てわかる” ファイバーチャネルSAN基礎講座(第2弾)~FC SAN設計における勘所とは?~
“見てわかる” ファイバーチャネルSAN基礎講座(第2弾)~FC SAN設計における勘所とは?~“見てわかる” ファイバーチャネルSAN基礎講座(第2弾)~FC SAN設計における勘所とは?~
“見てわかる” ファイバーチャネルSAN基礎講座(第2弾)~FC SAN設計における勘所とは?~
Brocade
?

Similar to Backdoor!! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方 (20)

VMwareユーザのためのdocker入門 ~Re:Virtualization Night #1~
VMwareユーザのためのdocker入門 ~Re:Virtualization Night #1~VMwareユーザのためのdocker入門 ~Re:Virtualization Night #1~
VMwareユーザのためのdocker入門 ~Re:Virtualization Night #1~
Masaomi Kudo
?
Osc2009 Do Xen Hara
Osc2009 Do Xen HaraOsc2009 Do Xen Hara
Osc2009 Do Xen Hara
Kazuhisa Hara
?
叠贬测痴别ってなんや
叠贬测痴别ってなんや叠贬测痴别ってなんや
叠贬测痴别ってなんや
Takuya ASADA
?
Lxc on cloud
Lxc on cloudLxc on cloud
Lxc on cloud
Yukihiko SAWANOBORI
?
Wakame Project - 自作クラウド研究会
Wakame Project - 自作クラウド研究会Wakame Project - 自作クラウド研究会
Wakame Project - 自作クラウド研究会
axsh co., LTD.
?
コンテナネットワーキング(颁狈滨)最前线
コンテナネットワーキング(颁狈滨)最前线コンテナネットワーキング(颁狈滨)最前线
コンテナネットワーキング(颁狈滨)最前线
Motonori Shindo
?
OpenStackネットワーキング管理者入門 - OpenStack最新情報セミナー 2014年8月
OpenStackネットワーキング管理者入門 - OpenStack最新情報セミナー 2014年8月OpenStackネットワーキング管理者入門 - OpenStack最新情報セミナー 2014年8月
OpenStackネットワーキング管理者入門 - OpenStack最新情報セミナー 2014年8月
VirtualTech Japan Inc.
?
Trema での Open vSwitch
Trema での Open vSwitchTrema での Open vSwitch
Trema での Open vSwitch
kazuyas
?
痴笔笔事始め
痴笔笔事始め痴笔笔事始め
痴笔笔事始め
npsg
?
20120822冲诲蝉迟苍技术交流会冲仮想化について
20120822冲诲蝉迟苍技术交流会冲仮想化について20120822冲诲蝉迟苍技术交流会冲仮想化について
20120822冲诲蝉迟苍技术交流会冲仮想化について
dstn
?
Unsafe Nested Virtualization on Intel CPU
Unsafe Nested Virtualization on Intel CPUUnsafe Nested Virtualization on Intel CPU
Unsafe Nested Virtualization on Intel CPU
Takaaki Fukai
?
FD.io 痴笔笔事始め
FD.io 痴笔笔事始めFD.io 痴笔笔事始め
FD.io 痴笔笔事始め
tetsusat
?
Mellanox Vxlan offload Performance on linux
Mellanox Vxlan offload Performance on linux Mellanox Vxlan offload Performance on linux
Mellanox Vxlan offload Performance on linux
Yuki Kitajima
?
勉強会0614 vagrant
勉強会0614 vagrant勉強会0614 vagrant
勉強会0614 vagrant
Yu Ito
?
近顷の顿辞肠办别谤ネットワーク
近顷の顿辞肠办别谤ネットワーク近顷の顿辞肠办别谤ネットワーク
近顷の顿辞肠办别谤ネットワーク
Yuji Oshima
?
Open vSwitchソースコードの全体像
Open vSwitchソースコードの全体像 Open vSwitchソースコードの全体像
Open vSwitchソースコードの全体像
Sho Shimizu
?
LinAction Theme Docker
LinAction Theme DockerLinAction Theme Docker
LinAction Theme Docker
cyberblack28 Ichikawa
?
第3回「マイクロソフトの仮想化と、クラウドの今後」(2011/06/16 on しすなま!) ②IBM資料
第3回「マイクロソフトの仮想化と、クラウドの今後」(2011/06/16 on しすなま!) ②IBM資料第3回「マイクロソフトの仮想化と、クラウドの今後」(2011/06/16 on しすなま!) ②IBM資料
第3回「マイクロソフトの仮想化と、クラウドの今後」(2011/06/16 on しすなま!) ②IBM資料
System x 部 (生!) : しすなま! @ Lenovo Enterprise Solutions Ltd.
?
VMwareユーザのためのdocker入門 ~Re:Virtualization Night #1~
VMwareユーザのためのdocker入門 ~Re:Virtualization Night #1~VMwareユーザのためのdocker入門 ~Re:Virtualization Night #1~
VMwareユーザのためのdocker入門 ~Re:Virtualization Night #1~
Masaomi Kudo
?
叠贬测痴别ってなんや
叠贬测痴别ってなんや叠贬测痴别ってなんや
叠贬测痴别ってなんや
Takuya ASADA
?
Wakame Project - 自作クラウド研究会
Wakame Project - 自作クラウド研究会Wakame Project - 自作クラウド研究会
Wakame Project - 自作クラウド研究会
axsh co., LTD.
?
コンテナネットワーキング(颁狈滨)最前线
コンテナネットワーキング(颁狈滨)最前线コンテナネットワーキング(颁狈滨)最前线
コンテナネットワーキング(颁狈滨)最前线
Motonori Shindo
?
OpenStackネットワーキング管理者入門 - OpenStack最新情報セミナー 2014年8月
OpenStackネットワーキング管理者入門 - OpenStack最新情報セミナー 2014年8月OpenStackネットワーキング管理者入門 - OpenStack最新情報セミナー 2014年8月
OpenStackネットワーキング管理者入門 - OpenStack最新情報セミナー 2014年8月
VirtualTech Japan Inc.
?
Trema での Open vSwitch
Trema での Open vSwitchTrema での Open vSwitch
Trema での Open vSwitch
kazuyas
?
痴笔笔事始め
痴笔笔事始め痴笔笔事始め
痴笔笔事始め
npsg
?
20120822冲诲蝉迟苍技术交流会冲仮想化について
20120822冲诲蝉迟苍技术交流会冲仮想化について20120822冲诲蝉迟苍技术交流会冲仮想化について
20120822冲诲蝉迟苍技术交流会冲仮想化について
dstn
?
Unsafe Nested Virtualization on Intel CPU
Unsafe Nested Virtualization on Intel CPUUnsafe Nested Virtualization on Intel CPU
Unsafe Nested Virtualization on Intel CPU
Takaaki Fukai
?
FD.io 痴笔笔事始め
FD.io 痴笔笔事始めFD.io 痴笔笔事始め
FD.io 痴笔笔事始め
tetsusat
?
Mellanox Vxlan offload Performance on linux
Mellanox Vxlan offload Performance on linux Mellanox Vxlan offload Performance on linux
Mellanox Vxlan offload Performance on linux
Yuki Kitajima
?
勉強会0614 vagrant
勉強会0614 vagrant勉強会0614 vagrant
勉強会0614 vagrant
Yu Ito
?
近顷の顿辞肠办别谤ネットワーク
近顷の顿辞肠办别谤ネットワーク近顷の顿辞肠办别谤ネットワーク
近顷の顿辞肠办别谤ネットワーク
Yuji Oshima
?
Open vSwitchソースコードの全体像
Open vSwitchソースコードの全体像 Open vSwitchソースコードの全体像
Open vSwitchソースコードの全体像
Sho Shimizu
?

Recently uploaded (11)

狈辞诲补滨迟蝉耻办颈冲反省観点の分类に基づく试合の振り返り支援システムに関する有用性検証冲顿贰滨惭2025
狈辞诲补滨迟蝉耻办颈冲反省観点の分类に基づく试合の振り返り支援システムに関する有用性検証冲顿贰滨惭2025狈辞诲补滨迟蝉耻办颈冲反省観点の分类に基づく试合の振り返り支援システムに関する有用性検証冲顿贰滨惭2025
狈辞诲补滨迟蝉耻办颈冲反省観点の分类に基づく试合の振り返り支援システムに関する有用性検証冲顿贰滨惭2025
Matsushita Laboratory
?
【卒业论文】深层学习によるログ异常検知モデルを用いたサイバー攻撃検知に関する研究
【卒业论文】深层学习によるログ异常検知モデルを用いたサイバー攻撃検知に関する研究【卒业论文】深层学习によるログ异常検知モデルを用いたサイバー攻撃検知に関する研究
【卒业论文】深层学习によるログ异常検知モデルを用いたサイバー攻撃検知に関する研究
harmonylab
?
【卒业论文】尝尝惭を用いた惭耻濒迟颈-础驳别苍迟-顿别产补迟别における反论の効果に関する研究
【卒业论文】尝尝惭を用いた惭耻濒迟颈-础驳别苍迟-顿别产补迟别における反论の効果に関する研究【卒业论文】尝尝惭を用いた惭耻濒迟颈-础驳别苍迟-顿别产补迟别における反论の効果に関する研究
【卒业论文】尝尝惭を用いた惭耻濒迟颈-础驳别苍迟-顿别产补迟别における反论の効果に関する研究
harmonylab
?
LF Decentralized Trust Tokyo Meetup 3
LF Decentralized Trust Tokyo Meetup 3LF Decentralized Trust Tokyo Meetup 3
LF Decentralized Trust Tokyo Meetup 3
LFDT Tokyo Meetup
?
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
CRI Japan, Inc.
?
実はアナタの身近にある!? Linux のチェックポイント/レストア機能 (NTT Tech Conference 2025 発表資料)
実はアナタの身近にある!? Linux のチェックポイント/レストア機能 (NTT Tech Conference 2025 発表資料)実はアナタの身近にある!? Linux のチェックポイント/レストア機能 (NTT Tech Conference 2025 発表資料)
実はアナタの身近にある!? Linux のチェックポイント/レストア機能 (NTT Tech Conference 2025 発表資料)
NTT DATA Technology & Innovation
?
测距センサと滨惭鲍センサを用いた指轮型デバイスにおける颜认証システムの提案
测距センサと滨惭鲍センサを用いた指轮型デバイスにおける颜认証システムの提案测距センサと滨惭鲍センサを用いた指轮型デバイスにおける颜认証システムの提案
测距センサと滨惭鲍センサを用いた指轮型デバイスにおける颜认証システムの提案
sugiuralab
?
第1回日本理学疗法推论学会学术大会での発表资料(2025年3月2日 高桥可奈恵)
第1回日本理学疗法推论学会学术大会での発表资料(2025年3月2日 高桥可奈恵)第1回日本理学疗法推论学会学术大会での発表资料(2025年3月2日 高桥可奈恵)
第1回日本理学疗法推论学会学术大会での発表资料(2025年3月2日 高桥可奈恵)
Matsushita Laboratory
?
贬补谤耻办颈厂丑颈苍办补飞补冲尝尝惭を利用した果树农家の経験知の対话的蓄积支援冲诲别颈尘2025
贬补谤耻办颈厂丑颈苍办补飞补冲尝尝惭を利用した果树农家の経験知の対话的蓄积支援冲诲别颈尘2025贬补谤耻办颈厂丑颈苍办补飞补冲尝尝惭を利用した果树农家の経験知の対话的蓄积支援冲诲别颈尘2025
贬补谤耻办颈厂丑颈苍办补飞补冲尝尝惭を利用した果树农家の経験知の対话的蓄积支援冲诲别颈尘2025
Matsushita Laboratory
?
ラズパイを使って作品を作ったらラズパイコンテストで碍厂驰赏を貰って、さらに、文化庁メディア芸术祭で审査员推荐作品に选ばれてしまった件?自作チップでラズパイ...
ラズパイを使って作品を作ったらラズパイコンテストで碍厂驰赏を貰って、さらに、文化庁メディア芸术祭で审査员推荐作品に选ばれてしまった件?自作チップでラズパイ...ラズパイを使って作品を作ったらラズパイコンテストで碍厂驰赏を貰って、さらに、文化庁メディア芸术祭で审査员推荐作品に选ばれてしまった件?自作チップでラズパイ...
ラズパイを使って作品を作ったらラズパイコンテストで碍厂驰赏を貰って、さらに、文化庁メディア芸术祭で审査员推荐作品に选ばれてしまった件?自作チップでラズパイ...
Industrial Technology Research Institute (ITRI)(工業技術研究院, 工研院)
?
空间オーディオを用いたヘッドパスワードの提案と音源提示手法の最适化
空间オーディオを用いたヘッドパスワードの提案と音源提示手法の最适化空间オーディオを用いたヘッドパスワードの提案と音源提示手法の最适化
空间オーディオを用いたヘッドパスワードの提案と音源提示手法の最适化
sugiuralab
?
狈辞诲补滨迟蝉耻办颈冲反省観点の分类に基づく试合の振り返り支援システムに関する有用性検証冲顿贰滨惭2025
狈辞诲补滨迟蝉耻办颈冲反省観点の分类に基づく试合の振り返り支援システムに関する有用性検証冲顿贰滨惭2025狈辞诲补滨迟蝉耻办颈冲反省観点の分类に基づく试合の振り返り支援システムに関する有用性検証冲顿贰滨惭2025
狈辞诲补滨迟蝉耻办颈冲反省観点の分类に基づく试合の振り返り支援システムに関する有用性検証冲顿贰滨惭2025
Matsushita Laboratory
?
【卒业论文】深层学习によるログ异常検知モデルを用いたサイバー攻撃検知に関する研究
【卒业论文】深层学习によるログ异常検知モデルを用いたサイバー攻撃検知に関する研究【卒业论文】深层学习によるログ异常検知モデルを用いたサイバー攻撃検知に関する研究
【卒业论文】深层学习によるログ异常検知モデルを用いたサイバー攻撃検知に関する研究
harmonylab
?
【卒业论文】尝尝惭を用いた惭耻濒迟颈-础驳别苍迟-顿别产补迟别における反论の効果に関する研究
【卒业论文】尝尝惭を用いた惭耻濒迟颈-础驳别苍迟-顿别产补迟别における反论の効果に関する研究【卒业论文】尝尝惭を用いた惭耻濒迟颈-础驳别苍迟-顿别产补迟别における反论の効果に関する研究
【卒业论文】尝尝惭を用いた惭耻濒迟颈-础驳别苍迟-顿别产补迟别における反论の効果に関する研究
harmonylab
?
LF Decentralized Trust Tokyo Meetup 3
LF Decentralized Trust Tokyo Meetup 3LF Decentralized Trust Tokyo Meetup 3
LF Decentralized Trust Tokyo Meetup 3
LFDT Tokyo Meetup
?
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
CRI Japan, Inc.
?
実はアナタの身近にある!? Linux のチェックポイント/レストア機能 (NTT Tech Conference 2025 発表資料)
実はアナタの身近にある!? Linux のチェックポイント/レストア機能 (NTT Tech Conference 2025 発表資料)実はアナタの身近にある!? Linux のチェックポイント/レストア機能 (NTT Tech Conference 2025 発表資料)
実はアナタの身近にある!? Linux のチェックポイント/レストア機能 (NTT Tech Conference 2025 発表資料)
NTT DATA Technology & Innovation
?
测距センサと滨惭鲍センサを用いた指轮型デバイスにおける颜认証システムの提案
测距センサと滨惭鲍センサを用いた指轮型デバイスにおける颜认証システムの提案测距センサと滨惭鲍センサを用いた指轮型デバイスにおける颜认証システムの提案
测距センサと滨惭鲍センサを用いた指轮型デバイスにおける颜认証システムの提案
sugiuralab
?
第1回日本理学疗法推论学会学术大会での発表资料(2025年3月2日 高桥可奈恵)
第1回日本理学疗法推论学会学术大会での発表资料(2025年3月2日 高桥可奈恵)第1回日本理学疗法推论学会学术大会での発表资料(2025年3月2日 高桥可奈恵)
第1回日本理学疗法推论学会学术大会での発表资料(2025年3月2日 高桥可奈恵)
Matsushita Laboratory
?
贬补谤耻办颈厂丑颈苍办补飞补冲尝尝惭を利用した果树农家の経験知の対话的蓄积支援冲诲别颈尘2025
贬补谤耻办颈厂丑颈苍办补飞补冲尝尝惭を利用した果树农家の経験知の対话的蓄积支援冲诲别颈尘2025贬补谤耻办颈厂丑颈苍办补飞补冲尝尝惭を利用した果树农家の経験知の対话的蓄积支援冲诲别颈尘2025
贬补谤耻办颈厂丑颈苍办补飞补冲尝尝惭を利用した果树农家の経験知の対话的蓄积支援冲诲别颈尘2025
Matsushita Laboratory
?
ラズパイを使って作品を作ったらラズパイコンテストで碍厂驰赏を貰って、さらに、文化庁メディア芸术祭で审査员推荐作品に选ばれてしまった件?自作チップでラズパイ...
ラズパイを使って作品を作ったらラズパイコンテストで碍厂驰赏を貰って、さらに、文化庁メディア芸术祭で审査员推荐作品に选ばれてしまった件?自作チップでラズパイ...ラズパイを使って作品を作ったらラズパイコンテストで碍厂驰赏を貰って、さらに、文化庁メディア芸术祭で审査员推荐作品に选ばれてしまった件?自作チップでラズパイ...
ラズパイを使って作品を作ったらラズパイコンテストで碍厂驰赏を貰って、さらに、文化庁メディア芸术祭で审査员推荐作品に选ばれてしまった件?自作チップでラズパイ...
Industrial Technology Research Institute (ITRI)(工業技術研究院, 工研院)
?
空间オーディオを用いたヘッドパスワードの提案と音源提示手法の最适化
空间オーディオを用いたヘッドパスワードの提案と音源提示手法の最适化空间オーディオを用いたヘッドパスワードの提案と音源提示手法の最适化
空间オーディオを用いたヘッドパスワードの提案と音源提示手法の最适化
sugiuralab
?

Backdoor!! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方

  • 1. Backdoor !! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方 2010/4/12 VTCライトニングトーク発表内容 しろやまたかゆき<shiro.t@gmail.com>
  • 2. Hypercall とは? l? ゲストOS からハイパーバイザを明示的に呼び出す方法 l? Binary Translation や VMEXIT/VMRESUME に比べコストが低い l? 呼び出し方法が低コスト l? ハイパーバイザに都合のいいデータのやり取りが可能 l? 準仮想化された OS で使用されている l? Xen 対応の Linux カーネルなど
  • 3. Xen での Hypercall の実装 l? 単純に int 命令でソフトウェア割り込みをかけているだけ l? Ring0 の Xen hyper-visor が割り込みをキャッチし、指定のルーチンを 呼び出している http://www.ylug.jp/download/hypercall_ylug_20061027.pdf
  • 4. Hypercall は準仮想化だけのもの? l? いえ、類似/同等の機能は完全仮想化のハイパーバイザにもあります! l? 性能上の理由 l? Binary Translation や VMEXIT/VMRESUME に比べコストが低い l? 仮想化ならではの機能の実現 l? VM間 / VM-Hypervisor 間の通信や制御 (VMCI)
  • 5. 例: VMCI int a, s, len; char buf[255]; struct sockaddr_vm addr = { 0 }; s = socket(PF_VSOCK_VMCI, SOCK_STREAM, 0); addr.svm_family = AF_VSOCK_VMCI; addr.svm_cid = VMADDR_CID_ANY; addr.svm_rid = 2000; bind(s, (struct sockaddr *) &addr, sizeofaddr); listen(s, 5); a = accept(s, (struct sockaddr *) &addr, &len); len = recv(a, buf, sizeof buf, 0); int a, s, len; char *buf = “Hello, world!”; struct sockaddr_vm addr = { 0 }; s = socket(PF_VSOCK_VMCI, SOCK_STREAM, 0); addr.svm_family = AF_VSOCK_VMCI; addr.svm_cid = GUEST2; addr.svm_rid = 2000; connect(s, (struct sockaddr *) &addr, sizeof addr); len = send(s, buf, len, 0); 基本はソケットプログラミング 通常のPF_INETの代わりに PF_VSOCK_VMCIに変更。 読み書き(send/recv)は変わらず Hyper-?visor Application Guest ?OS 仮想マシン Application Guest ?OS 仮想マシン Server Client
  • 6. ESX / Hyper-V の Hypercall l? では、ESX / Hyper-V の Hypercall って どうやってるの? ソースコードにきいてみよう!
  • 7. VMware の場合: open-vm-tools Open Virtual Machine Tools l? vmware-tools のソースコードは公開されている (2007.9.4~) l? Linux, FreeBSD, Solaris 用 l? vmsync など、標準の VMware Tools にないモジュールも存在 http://open-?vm-?tools.sourceforge.net/
  • 8. Microsoft の場合 l? Hyper-V の統合サービス(Linux向け)のソースコードを公開!(2009.7.21) l? これを読めば Hyper-V の hypercall も解明できる?
  • 9. で、どうやってダウンロードすればいいの? l? MS のサイトを漁りまわったけどソースコードを発見できず!! l? 公開を報じる国内記事は多々あれど、ソースそのもののリンクはどこにもない l? 駄目ぢゃん、っと思ってたら...
  • 10. で、どうやってダウンロードすればいいの? l? Linux-Kernel ML に Greg-KH 氏が投稿していた l? パッチを 54 分割して... l? 何とか苦労して取り出しました l? 最近のカーネルソースには既に含まれている模様
  • 11. ソースツリー: open-vm-tools の場合 l? open-vm-tools l? 綺麗な階層構造、Makfile 完備 l? さまざまなOSでのビルドを前提としている l? コード数、約24万行 - 「find –name ‘*.[ch]’ -print0 | xargs -0 wc –l 」の実行結果より
  • 12. ソースツリー: open-vm-tools の場合 l? open-vm-tools の階層構造 +-?-? autom4te.cache/ +-?-? checkvm/ +-?-? config/ +-?-? docs/ +-?-? hgfsclient/ +-?-? hgfsmounter/ +-?-? lib/ +-?-? libguestlib/ +-?-? libvmtools/ +-?-? m4/ +-?-? modules/ | ? ? ?+-?-? freebsd/ | ? ? ?+-?-? linux/ | ? ? ?+-?-? solaris/ +-?-? rpctool/ +-?-? scripts/ +-?-? services/ | ? ? ?+-?-? plugins/ || ? ? ?+-?-? vmtoolsd/ +-?-? tests/ +-?-? toolbox/ +-?-? vmblock-?fuse/ +-?-? vmware-?user/ +-?-? vmware-?user-?suid-?wrapper/ +-?-? xferlogs/ ? | ? ? ?+-?-? linux/ | ? ? ?| ? ? ?+-?-? pvscsi/ | ? ? ?| ? ? ?+-?-? shared/ | ? ? ?| ? ? ?+-?-? vmblock/ | ? ? ?| ? ? ?+-?-? vmci/ | ? ? ?| ? ? ?+-?-? vmhgfs/ | ? ? ?| ? ? ?+-?-? vmmemctl/ | ? ? ?| ? ? ?+-?-? vmsync/ | ? ? ?| ? ? ?+-?-? vmxnet/ | ? ? ?| ? ? ?+-?-? vsock/ 独自のツリー構造 多くのOSに対応 共通化モジュール、ユーザランドツール、 ドライバなど綺麗に分離されている
  • 13. ソースツリー: Hyper-V の場合 l? linux integration component l? linux-kernel に対するパッチで、Linux にべったりの構造 - カーネルパッチだけ?ユーザランドに何もない?? l? driver/staging/hv 以下に集中配置 l? 約2万行
  • 14. ソースツリー: Hyper-V の場合 ファイル一覧 BlkVsc.c HvVpApi.h Vmbus.c Channel.c Kconfig VmbusApi.h Channel.h List.h VmbusChannelInterface.h ChannelInterface.c Makefile VmbusPacketFormat.h ChannelInterface.h Makefile.rej VmbusPrivate.h ChannelMessages.h NetVsc.c blkvsc_drv.c ChannelMgmt.c NetVsc.h hv.diff ChannelMgmt.h NetVscApi.h logging.h Connection.c RingBuffer.c netvsc_drv.c Hv.c RingBuffer.h nvspprotocol.h Hv.h RndisFilter.c osd.c HvHalApi.h RndisFilter.h osd.h HvHcApi.h Sources.c rndis.h HvPtApi.h StorVsc.c storvsc_drv.c HvStatus.h StorVscApi.h vmbus.h HvSynicApi.h TODO vmbus_drv.c HvTypes.h VersionInfo.h vstorage.h
  • 15. Linux への侵食方法:VMware の場合 あくまで「物理デバイスに対するドライバ」の立場 l? VMware-tools の有無に関わらず、仮想デバイスが存在する前提 l? PCIバス上にデバイスがつながっているように見える l? PCIバスのデバイス検出手順に従い、ドライバがロードされていく l? VendorID: 0x15AD で、指定 の DeviceID をもつドライバが 選定される l? 選定されたドライバのprobe 関数を 実行して、本当に対応するデバイスか を確認させる l? 失敗が帰ったら、次の候補となる ドライバを探す /* Our own PCI IDs * VMware SVGA II (Unified VGA) * VMware SVGA (PCI Accelerator) * VMware vmxnet (Idealized NIC) * VMware vmxscsi (Abortive idealized SCSI controller) * VMware chipset (Subsystem ID for our motherboards) * VMware e1000 (Subsystem ID) * VMware vmxnet3 (Uniform Pass Through NIC) */ #define PCI_VENDOR_ID_VMWARE 0x15AD #define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 #define PCI_DEVICE_ID_VMWARE_SVGA 0x0710 #define PCI_DEVICE_ID_VMWARE_NET 0x0720 #define PCI_DEVICE_ID_VMWARE_SCSI 0x0730 #define PCI_DEVICE_ID_VMWARE_VMCI 0x0740 #define PCI_DEVICE_ID_VMWARE_CHIPSET 0x1976 #define PCI_DEVICE_ID_VMWARE_82545EM 0x0750 /* single port */ #define PCI_DEVICE_ID_VMWARE_82546EB 0x0760 /* dual port */ #define PCI_DEVICE_ID_VMWARE_EHCI 0x0770 #define PCI_DEVICE_ID_VMWARE_UHCI 0x0774 #define PCI_DEVICE_ID_VMWARE_XHCI 0x0778 #define PCI_DEVICE_ID_VMWARE_1394 0x0780 #define PCI_DEVICE_ID_VMWARE_BRIDGE 0x0790 #define PCI_DEVICE_ID_VMWARE_ROOTPORT 0x07A0 #define PCI_DEVICE_ID_VMWARE_VMXNET3 0x07B0 #define PCI_DEVICE_ID_VMWARE_VMXWIFI 0x07B8 #define PCI_DEVICE_ID_VMWARE_PVSCSI 0x07C0 #define PCI_DEVICE_ID_VMWARE_82574 0x07D0 lib/include/vm_device_version.h ?より
  • 16. Linux への侵食方法:VMware の場合 余談: vmxnet の Morphing l? ESX 2.x では、vlance と vmxnet は区別されてました l? vlance vendorID: 0x1022(AMD) deviceID: 0x2000 l? vmxnet vendorID: 0x15AD(VMware) deviceID: 0x0720 l? ESX 3.x 以降で、vlance -> vmxnet の入れ替えしました?
  • 17. Linux への侵食方法:VMware の場合 余談: vmxnet の Morphing l? ESX 3.x 以降の vlance は、vmxnet を「兼用」している l? たまたま、AMD-PCNET が 32byte しか IO空間を使ってなかった点を利用 l? 64byte まで取れるIO空間の後ろ32byte に vmxnet の IO空間を追加 /* * Since this is a vlance adapter we can only use it if * its I/0 space is big enough for the adapter to be * capable of morphing. This is the first requirement * for this adapter to potentially be morphable. The * layout of a morphable LANCE adapter is * * I/O space: * * |------------------| * | LANCE IO PORTS | * |------------------| * | MORPH PORT | * |------------------| * | VMXNET IO PORTS | * |------------------| * * VLance has 8 ports of size 4 bytes, the morph port is 4 bytes, and * Vmxnet has 10 ports of size 4 bytes. * * We shift up the ioaddr with the size of the LANCE I/O space since * we want to access the vmxnet ports. We also shift the ioaddr up by * the MORPH_PORT_SIZE so other port access can be independent of * whether we are Vmxnet or a morphed VLance. This means that when * we want to access the MORPH port we need to subtract the size * from ioaddr to get to it. */
  • 18. Linux への侵食方法:VMware の場合 余談: vmxnet の Morphing l? vmxnet ドライバの probe 関数(vmxnet_probe_device)の挙動 l? PCI の Vendor ID を取得 - 0x15AD (VMware) なら、そのまま vmxnet デバイスと判断 ? 旧 vmxnet との互換性の確保 - 0x1022 (AMD) の場合 ? IO空間のサイズを取得し、64byte とサイズを比較 ? それより小さかったら? 「うちの子じゃない」 で probe に失敗を返す ? 64byte 以上なら、「うちの子だから」と認定 ? morph port に outw で値を書き込み、vmxnet として振舞わせる
  • 19. Linux への侵食方法:VMware の場合 static int vmxnet_morph_device(unsigned int morphAddr) // IN { uint16 magic; /* Read morph port to verify that we can morph the adapter. */ magic = inw(morphAddr); if (magic != LANCE_CHIP && magic != VMXNET_CHIP) { printk(KERN_ERR "Invalid magic, read: 0x%08X?n", magic); return -1; } /* Morph adapter. */ outw(VMXNET_CHIP, morphAddr); /* Verify that we morphed correctly. */ magic = inw(morphAddr); if (magic != VMXNET_CHIP) { printk(KERN_ERR "Couldn't morph adapter. Invalid magic, read: 0x%08X?n", magic); goto morph_back; } return 0; morph_back: /* Morph back to LANCE hw. */ outw(LANCE_CHIP, morphAddr); return -1; }
  • 20. VMM Linux への侵食方法:VMware の場合 l? あくまで正規のデバイスドライバとしてロードされる l? 比較的、物理デバイスに近いエミュレーションがなされている l? Backdoor を使ってデバイスエミュレーションをある程度「バイパス」する Linux ?kernel vmxnet_drv VGA LSILogic NIC VGA SCSI VendorID: ?xxxx DeviceID ?: ?xxxx VendorID: ?xxxx DeviceID ?: ?xxxx VendorID: ?xxxx DeviceID ?: ?xxxx PCI ?バス Backdoor vmsync vmUser vmmemctl VMkernel vmtools ? 提供ドライバ ネイティブドライバ
  • 21. Backdoor : IO空間の in/out 命令 l? VMware の Backdoor は、指定のIO空間への in /out 命令 l? in / out : x86 のもつ IO 空間へのデータの読み書きの命令 l? NICなどの一般的なデバイスは IO空間の一部を通じてデータをやり取りする - グラフィックカードなどのより大きな空間を必要とするものは、メモリ空間 にマップされる - PCI は IO空間 / メモリマップのどちらの方法もサポートする l? VMware ではこの in / out 命令を転用している l? 詳細: http://chitchat.at.infoseek.co.jp/vmware/backdoorj.html
  • 22. Backdoor : IO空間の in/out 命令 static ?void BalloonTimerHandler(void ?*clientData) ?// ?IN { Balloon ?*b ?= ?(Balloon ?*) ?clientData;? uint32 ?target ?= ?0;? ?// ?Silence ?compiler ?warning. int ?status;? /* ?update ?stats ?*/ STATS_INC(b-?>stats.timer);? /* ?reset, ?if ?specified ?*/ if ?(b-?>resetFlag) ?{ BalloonReset(b);? } /* ?contact ?monitor ?via ?backdoor ?*/ status ?= ?BalloonMonitorGetTarget(b, ?&target);? /* ?decrement ?slowPageAllocationCycles ?counter ?*/ if ?(b-?>slowPageAllocationCycles ?> ?0) ?{ b-?>slowPageAllocationCycles-?-?;? } if ?(status ?== ?BALLOON_SUCCESS) ?{ /* ?update ?target, ?adjust ?size ?*/ b-?>nPagesTarget ?= ?target;? (void) ?BalloonAdjustSize(b, ?target);? } }
  • 23. Backdoor : IO空間の in/out 命令 static ?void BalloonTimerHandler(void ?*clientData) ?// ?IN { Balloon ?*b ?= ?(Balloon ?*) ?clientData;? uint32 ?target ?= ?0;? ?// ?Silence ?compiler ?warning. int ?status;? /* ?update ?stats ?*/ STATS_INC(b-?>stats.timer);? /* ?reset, ?if ?specified ?*/ if ?(b-?>resetFlag) ?{ BalloonReset(b);? } /* ?contact ?monitor ?via ?backdoor ?*/ status ?= ?BalloonMonitorGetTarget(b, ?&target);? /* ?decrement ?slowPageAllocationCycles ?counter ?*/ if ?(b-?>slowPageAllocationCycles ?> ?0) ?{ b-?>slowPageAllocationCycles-?-?;? } if ?(status ?== ?BALLOON_SUCCESS) ?{ /* ?update ?target, ?adjust ?size ?*/ b-?>nPagesTarget ?= ?target;? (void) ?BalloonAdjustSize(b, ?target);? } } static ?int BalloonMonitorGetTarget(Balloon ?*b, ? ? ? ? ?// ?IN uint32 ?*target) ?// ?OUT { Backdoor_proto ?bp;? unsigned ?long ?limit;? uint32 ?limit32;? uint32 ?status;? limit ?= ?OS_ReservedPageGetLimit();? /* ?Ensure ?limit ?fits ?in ?32-?bits ?*/ limit32 ?= ?(uint32)limit;? if ?(limit32 ?!= ?limit) ?{ return ?BALLOON_FAILURE;? } /* ?prepare ?backdoor ?args ?*/ bp.in.cx.halfs.low ?= ?BALLOON_BDOOR_CMD_TARGET;? bp.in.size ?= ?limit;? /* ?invoke ?backdoor ?*/ Backdoor_Balloon(&bp);? /* ?parse ?return ?values ?*/ status ? ?= ?bp.out.ax.word;? *target ?= ?bp.out.bx.word;?
  • 24. Backdoor : IO空間の in/out 命令 static ?void BalloonTimerHandler(void ?*clientData) ?// ?IN { Balloon ?*b ?= ?(Balloon ?*) ?clientData;? uint32 ?target ?= ?0;? ?// ?Silence ?compiler ?warning. int ?status;? /* ?update ?stats ?*/ STATS_INC(b-?>stats.timer);? /* ?reset, ?if ?specified ?*/ if ?(b-?>resetFlag) ?{ BalloonReset(b);? } /* ?contact ?monitor ?via ?backdoor ?*/ status ?= ?BalloonMonitorGetTarget(b, ?&target);? /* ?decrement ?slowPageAllocationCycles ?counter ?*/ if ?(b-?>slowPageAllocationCycles ?> ?0) ?{ b-?>slowPageAllocationCycles-?-?;? } if ?(status ?== ?BALLOON_SUCCESS) ?{ /* ?update ?target, ?adjust ?size ?*/ b-?>nPagesTarget ?= ?target;? (void) ?BalloonAdjustSize(b, ?target);? } } static ?int BalloonMonitorGetTarget(Balloon ?*b, ? ? ? ? ?// ?IN uint32 ?*target) ?// ?OUT { Backdoor_proto ?bp;? unsigned ?long ?limit;? uint32 ?limit32;? uint32 ?status;? limit ?= ?OS_ReservedPageGetLimit();? /* ?Ensure ?limit ?fits ?in ?32-?bits ?*/ limit32 ?= ?(uint32)limit;? if ?(limit32 ?!= ?limit) ?{ return ?BALLOON_FAILURE;? } /* ?prepare ?backdoor ?args ?*/ bp.in.cx.halfs.low ?= ?BALLOON_BDOOR_CMD_TARGET;? bp.in.size ?= ?limit;? /* ?invoke ?backdoor ?*/ Backdoor_Balloon(&bp);? /* ?parse ?return ?values ?*/ status ? ?= ?bp.out.ax.word;? *target ?= ?bp.out.bx.word;? static ?INLINE void ?Backdoor_Balloon(Backdoor_proto ?*myBp) ?{ myBp-?>in.ax.word ?= ?BALLOON_BDOOR_MAGIC;? myBp-?>in.dx.halfs.low ?= ?BALLOON_BDOOR_PORT;? Backdoor_InOut(myBp);? }
  • 25. Backdoor : IO空間の in/out 命令 Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT { uint32 dummy; __asm__ __volatile__( #ifdef __PIC__ "pushl %%ebx" "?n?t" #endif "pushl %%eax" "?n?t" "movl 20(%%eax), %%edi" "?n?t" "movl 16(%%eax), %%esi" "?n?t" "movl 12(%%eax), %%edx" "?n?t" "movl 8(%%eax), %%ecx" "?n?t" "movl 4(%%eax), %%ebx" "?n?t" "movl (%%eax), %%eax" "?n?t" "inl %%dx, %%eax" "?n?t" "xchgl %%eax, (%%esp)" "?n?t" "movl %%edi, 20(%%eax)" "?n?t" "movl %%esi, 16(%%eax)" "?n?t" "movl %%edx, 12(%%eax)" "?n?t" "movl %%ecx, 8(%%eax)" "?n?t" "movl %%ebx, 4(%%eax)" "?n?t" "popl (%%eax)" "?n?t" #ifdef __PIC__ "popl %%ebx" "?n?t" #endif : "=a" (dummy) : "0" (myBp) /* * vmware can modify the whole VM state without the compiler knowing * it. So far it does not modify EFLAGS. --hpreg */ : #ifndef __PIC__ "ebx", #endif "ecx", "edx", "esi", "edi", "memory" ); } この inl 命令の実行した瞬間に VMkernel 側に処理が渡り、該当する 機能が実行され、結果が vCPU の EAX 、ECX 、 EDX 、 ESI、EDI レジスタ に書き込まれる
  • 26. Hyper-V のドライバイメージ l? Hyper-V の場合は、デバイスではなく「バス」を追加している l? PCI バスの下に、なんかバスがある... l? なんかバスが「外」に伸びてるっぽい... VMM Linux ?kernel レガシNIC VGA IDE VendorID: ?xxxx DeviceID ?: ?xxxx VendorID: ?xxxx DeviceID ?: ?xxxx VendorID: ?xxxx DeviceID ?: ?xxxx PCI ?バス ネイティブドライバ 21140 VGA IDE VMBUS Backdoor vmbus_drv netvsc_drv storage_drv NIC SCSI Hyper-?V ParentVM
  • 27. Hyper-V のドライバイメージ l? Hyper-V の場合は、デバイスではなく「バス」を追加している l? PCI バスの下に、なんかバスがある... l? なんかバスが「外」に伸びてるっぽい...
  • 28. Linux の侵食方法 : Hyper-V の場合 l? とにかく vmbus_drv デバイスドライバをロードする l? VMBUS という何らかの「バス」があると Linux に誤認させる l? VMBUS も、PCI と同じようにバス上のノードの検出を行う - VendorID と Device ID ではなく、ClassID という GUID で識別 - ノードごと、netvsc_drv, storagevsc_drv, blkvsc_drv がロードされる ? VSC : Virtualization Service Client の略 l? 各 VSC はデバイスドライバだが、その下にはエミュレーションされたデバイス はまったく存在しない!!
  • 29. Linux の侵食方法 : Hyper-V の場合 http://enterprise.watch.impress.co.jp/cda/parts/image_for_link/41502-?13748-?4-?1.html 本当にこの通りでした...
  • 30. Linux の侵食方法 : Hyper-V の場合 もう少し詳しい 階層構造 l? 大きく4層に分かれる l? *_drv : Linux のデバイスドライバ(カーネルモジュール)としての体裁を整える l? Vsc, Vmbus : 各ドライバの実態となる実装 l? Channel, Connection : VMBUS の通信機能の実装 l? osd : メモリ確保など OS機能の抽象化 l? Hv : Hyper-V との 実際のインターフェイス Linux ?kernel osd VMM Vmbus vmbus_drvstoragevsc_drvnetvsc_drv blcvsc_drv Hv Channel Connection Channel ?Mgmt StorVscNetVsc BlcVsc Linux ?Kernel ?とのインターフェイス ドライバー中心部分 VMBUS ?通信機能
  • 31. Backdoor : そのメモリに触ると... Hyper-V のバックドアは特定のメモリアドレス l? Hv はロードされると以下の振る舞いをする l? CPUID 命令を実行し、Hyper-V の上かを確認する - CPUID(1) の ECXの31bit 目を確認 l? 続けて CPUID 命令を実行し、ハイパーバイザのベンダー(!)や バージョンを取得する l? メモリを1ページ確保する - これは通常の valloc が使用され、実行時により異なるページが 割り当てられる l? wmsr でそのメモリの物理アドレスを vCPU に書き込む(!) - MSR: Model Specific Register ? PentiumPro 以降のCPUにある、製品独自の設定を保存したり、 プロファイリング用のカウンタとなるレジスタ ? 詳細: http://mcn.oops.jp/wiki/index.php?CPU%2FCPUID%2FMSR l? 以降、Hypercall はこのメモリへのアクセスすると、Hypercall が発生する
  • 32. Backdoor : Hv初期化部分、Hyper-V 上かを確認 Name: HvQueryHypervisorPresence() Description: Query the cpuid for presense of windows hypervisor --*/ static int HvQueryHypervisorPresence ( void ) { unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; unsigned int op; eax = 0; ebx = 0; ecx = 0; edx = 0; op = HvCpuIdFunctionVersionAndFeatures; do_cpuid(op, &eax, &ebx, &ecx, &edx); return (ecx & HV_PRESENT_BIT); }
  • 33. Backdoor : Hv初期化部分、Hyper-V 上かを確認 Name: HvQueryHypervisorPresence() Description: Query the cpuid for presense of windows hypervisor --*/ static int HvQueryHypervisorPresence ( void ) { unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; unsigned int op; eax = 0; ebx = 0; ecx = 0; edx = 0; op = HvCpuIdFunctionVersionAndFeatures; do_cpuid(op, &eax, &ebx, &ecx, &edx); return (ecx & HV_PRESENT_BIT); } typedef enum _HV_CPUID_FUNCTION { HvCpuIdFunctionVersionAndFeatures = 0x00000001, HvCpuIdFunctionHvVendorAndMaxFunction = 0x40000000, HvCpuIdFunctionHvInterface = 0x40000001, // // The remaining functions depend on the value of HvCpuIdFunctionInterface // HvCpuIdFunctionMsHvVersion = 0x40000002, HvCpuIdFunctionMsHvFeatures = 0x40000003, HvCpuIdFunctionMsHvEnlightenmentInformation = 0x40000004, HvCpuIdFunctionMsHvImplementationLimits = 0x40000005 } HV_CPUID_FUNCTION, *PHV_CPUID_FUNCTION;
  • 34. Backdoor : Hv初期化部分、Hyper-V 上かを確認 Name: HvQueryHypervisorPresence() Description: Query the cpuid for presense of windows hypervisor --*/ static int HvQueryHypervisorPresence ( void ) { unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; unsigned int op; eax = 0; ebx = 0; ecx = 0; edx = 0; op = HvCpuIdFunctionVersionAndFeatures; do_cpuid(op, &eax, &ebx, &ecx, &edx); return (ecx & HV_PRESENT_BIT); } static inline void do_cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { __asm__ __volatile__("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (op), "c" (ecx)); }
  • 35. Backdoor : Hv初期化部分、Hyper-V 上かを確認 Name: HvQueryHypervisorPresence() Description: Query the cpuid for presense of windows hypervisor --*/ static int HvQueryHypervisorPresence ( void ) { unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; unsigned int op; eax = 0; ebx = 0; ecx = 0; edx = 0; op = HvCpuIdFunctionVersionAndFeatures; do_cpuid(op, &eax, &ebx, &ecx, &edx); return (ecx & HV_PRESENT_BIT); } // // #defines // #define HV_PRESENT_BIT 0x80000000
  • 36. Backdoor : Hv初期化部分、Hyper-V 上かを確認 Hyper-V 上の仮想マシンでの CPUID 。確かに ECX の31bit目が 立っている ESX上の仮想マシン 31bit 目は立っていない 0x8C082201 0x80000000 0x80000000 OR 0x00080201 0x80000000 0x00000000 OR
  • 37. Backdoor : Hv初期化部分、アクセス用のアドレスを設定 if ?(gHvContext.GuestId ?== ?HV_LINUX_GUEST_ID) { // ?Allocate ?the ?hypercall ?page ?memory //virtAddr ?= ?PageAlloc(1);? virtAddr ?= ?VirtualAllocExec(PAGE_SIZE);? if ?(!virtAddr) { DPRINT_ERR(VMBUS, ?"unable ?to ?allocate ?hypercall ?page!!");? goto ?Cleanup;? } hypercallMsr.Enable ?= ?1;? //hypercallMsr.GuestPhysicalAddress ?= ?Logical2PhysicalAddr(virtAddr) ?>> ?PAGE_SHIFT;? hypercallMsr.GuestPhysicalAddress ?= ?Virtual2Physical(virtAddr) ?>> ?PAGE_SHIFT;? WriteMsr(HV_X64_MSR_HYPERCALL, ?hypercallMsr.AsUINT64);? // ?Confirm ?that ?hypercall ?page ?did ?get ?setup. hypercallMsr.AsUINT64 ?= ?0;? hypercallMsr.AsUINT64 ?= ?ReadMsr(HV_X64_MSR_HYPERCALL);? if ?(!hypercallMsr.Enable) { DPRINT_ERR(VMBUS, ?"unable ?to ?set ?hypercall ?page!!");? goto ?Cleanup;? } gHvContext.HypercallPage ?= ?virtAddr;? osd.c にて定義。単に __valloc を 呼び出しているのみ。 単なるメモリ確保のため、どのアドレスが 変えるかは実行依存の模様 仮想アドレスを物理アドレスに書き換えた後、 CPU の MSR レジスタにアドレスを書き込む
  • 38. Backdoor : Hypercall の実際 static u64 HvDoHypercall ( u64 Control, void* Input, void* Output ) { #ifdef CONFIG_X86_64 u64 hvStatus=0; u64 inputAddress = (Input)? GetPhysicalAddress(Input) : 0; u64 outputAddress = (Output)? GetPhysicalAddress(Output) : 0; volatile void* hypercallPage = gHvContext.HypercallPage; DPRINT_DBG(VMBUS, "Hypercall <control %llx input phys %llx virt %p output phys %llx virt %p hypercall %p>", Control, inputAddress, Input, outputAddress, Output, hypercallPage); __asm__ __volatile__ ("mov %0, %%r8" : : "r" (outputAddress): "r8"); __asm__ __volatile__ ("call *%3" : "=a"(hvStatus): "c" (Control), "d" (inputAddress), "m" (hypercallPage)); DPRINT_DBG(VMBUS, "Hypercall <return %llx>", hvStatus); return hvStatus; RCXに命令コードを、RDX に入力データのアドレスを 突っ込んだ後、hypercallPage に call でジャンプし、 Hypercall を行っている (コールゲート?)
  • 39. Backdoor : そのメモリに触ると... l? 割り込み、どうするのん? l? VMware の場合、各デバイスは PCI 上のデバイスのため、PCIバスを通じて 個々のデバイスが (ゲスト)OSへ 割り込みをかけることができた - = VMM 側からゲストOSにデータを投げることができた l? Hyper-V の場合は? l? Linux Intergrated Module では、 IRQ 5 を VMBUS の割り込みとして使用
  • 40. 余談: なぜ、Hyper-V の起動ディスクは IDE only なのか l? VMBUS がないと統合モジュールが動かないため l? OS ロード前は、VMBUS などというバスを認識できない l? そもそも 仮想マシンの上の BIOS レベルで VMBUS ドライバを実装する必要 l? OS ロード後なら、追加的に VMBUS をロードできる
  • 41. まとめ l? 同じハイパーバイザ型の 仮想化ソフトウェアでも、Hypercall の 方法は各社各様 l? 意外ときっちり実装している ESX の VMM l? vmxnet ドライバも割と普通に IO 処理を行っている l? 物理とは大きく異なる Hyper-V の VMM l? エミュレートされたデバイスとは別に、本当に架空のデバイスを生成 l? VMBUS という架空のバスを通じて架空のデバイスを接続 l? 原理的に、morphing はできない。 - エミュレートデバイスと架空のデバイスは永久に混在する見込み