ãã£ã¨ãããã¢ãã«ãªã£ã mingw-w64
åãå ´éããªè©±é¡ã ããx64 Windows åãã®ãã¼ã«ãã§ã¼ã³ã«å ããããé£èºçãªé²åã«ã¤ãã¦ãx64 Windows åãã®ä¾å¤å¦çãã ãããåãããããã«è©±ãã (ã«ã¼ãã«ï¼VM Advent Calendar : 1010+1001/01/11 å)
x86âx64
Windows ã¯ãã®ãã©ãããã©ã¼ã ã®å¤åã«ãã£ã¦ãæ§ã ãªé¨åãå¤åãããããã¦ãè²ã ãªé¨åãé²åãããä¾å¤ãã³ããªã³ã°ããã®ã²ã¨ã¤ã ããã®ä»£ãããã³ã³ãã¤ã©ãããã¢ãªã¢ãã§ãªãã¨ãã®æ©æµãå¾ããã¨ãã§ããªããx86 ç¨ã® Windows ãã¿ã¼ã²ãããªãã°ããªãè ã£ãã³ã³ãã¤ã©ã§ãä¸ä¸åã®å®è¡ãã¡ã¤ã«ãå¾ãããããx64 ã§ã¯ããã¯ãããªããå ·ä½çã«ã¯æ¬¡ã®é¨åãããã
- x64 ç¨æ¨æº ABI ã®æ´å
- ã¬ã¸ã¹ã¿æ¸¡ãã«ãªã£ãã®ã¯ããªãã®ãã©ã¹ã ããé¢æ°ã®ãããã¼ã°ã¨ã¨ããã¼ã°ã®å½¢ã¯å¤§ããå¶ç´ããããã¨ã«ãªã£ããx86 ã ã¨å°ãªãã¨ãé¢æ°ãããã¼ã°ãã¨ããã¼ã°ã®å½¢ã¯ã³ã³ãã¤ã©å¥½ã¿ã®ä»»æã®ãã®ã使ç¨ã§ããã
- ä¾å¤ãã³ããªã³ã°ã®åç·¨
- ãã¼ãã«ãã¼ã¹ã®ä¾å¤ãã³ããªã³ã°ãæ¨æºã«ãªããã¨ã§ãã»ãã¥ãªãã£ã¨ããã©ã¼ãã³ã¹ã®åä¸ããã ãå¼å®³ãã
mingw-w64 ã¨ã¯
32/64-bit å
±ç¨ã® Windows åããã¼ã«ãã§ã¼ã³ã§ãããgcc ã binutils ã¨ãã£ããã¼ã«ã使ç¨ã㦠Windows åãã®ãã¤ãã£ãã¢ããªã±ã¼ã·ã§ã³ãä½æãããã¨ãã§ãããç©æ¥µçãªè²¢ç®ã«ãã£ã¦ã¦ã¼ã¶ã¢ã¼ãã¢ããªã±ã¼ã·ã§ã³ãä½ãåã«ã¯ã»ã¨ãã©ç³ãåãªãã»ã©ã«é²åãã¦ãããã«ã¼ãã«ã¢ã¼ãã®ãã©ã¤ããä½ããªããã¨ã¯ãªãã
ãã ãã«ã¼ãã«ã¢ã¼ããã©ã¤ããç¹ã« 64-bit åãã®ãã®ãä½ãã«ã¯ãæ大ã®é害ãåå¨ãããä¾å¤å¦çã§ããã
SEH (Structured Exception Handling)
SEH (æ§é åä¾å¤å¦ç) ã¯ãWindows ã«åå¨ããä½ã¬ãã«ã®ä¾å¤å¦çæ©æ§ã§ãããä¾ãã°ã次ã®ããã«ä½¿ç¨ããã
__try { /** ä¾å¤çºçã®å¯è½æ§ããããã³ãã© **/ } __except (EXCEPTION_EXECUTE_HANDLER) { /** ä¾å¤çºçæã®å¦ç **/ } __finally { /** ä½ããããã¨å®è¡ããã«ã¼ãã³ **/ }
ããã«ãã£ã¦ãèªåã§ã«ã¹ã¿ã ã®ã¨ã©ã¼å¦çã (C++ ä¾å¤ãªã©ã®é«ç´ãªãã®ãããã¼ãé¤ç®ãªã©ã® CPU ä¾å¤ã¾ã§ãã£ãããããã³ãã©ã¨ãã¦) æ¸ããã¨ãã§ããã
ããããªããããã㯠x86 㨠x64 ã§å¤§ãããã®æ©æ§ãç°ãªãã
x86 ã®å ´å
x86 ç¨ã® SEH ã¯åºæ¬çã«ã¹ã¿ãã¯ãã¼ã¹ã®ãã®ã ãã¹ã¿ãã¯ã«ä¾å¤ãã³ãã©ã«é¢ããæ å ±ãç½®ãã以åã«è¨å®ããã¦ããä¾å¤ãã³ãã©ããªã³ã¯ããã·ã¹ãã ã«ç»é²ããããããªæãã
function1âfunction2âfunction3âfunction4âfunction5 ã¨ããå¼ã³åºãå±¥æ´ãããå ´å: +---------------------------+ +------------------------+ +------------------------+ +------------------------+ +------------------------+ | fs:0 (ä¾å¤ç»é²ã¬ã³ã¼ã) |<----| function5 ã®ä¾å¤å¦ç |---->| function2 ã®ä¾å¤å¦ç |---->| function1 ã®ä¾å¤å¦ç |---->| ããã©ã«ãã®ä¾å¤å¦ç | +---------------------------+ +------------------------+ +------------------------+ +------------------------+ +------------------------+
ä¾å¤ç»é²ã¬ã³ã¼ãã¯ãããã __try ãããã¯ã«å
¥ã£ãã¨ããã§ãªã³ã¯ã¨ã·ã¹ãã ã¸ã®ç»é²ãè¡ããã次ã®å½ä»¤ã®ä¾å¤ããã¯ãã¡ããåç
§ãããã¨ã«ãªãã(ããã«ã¯è¥å¹²ã®ãªã¼ãã¼ããããããã) ããä¾å¤ãçºçããã¨ããfunction5 ã®ä¾å¤ãã£ã«ã¿ã¯ããããã³ãã«ãããããããªãããããã¯ãå®è¡ãç¶ç¶ããããããããªãããããã¯èªåã§å¦çãã§ããªãã£ããªã©ã®çç±ã§ãå¾ãã«ããä¾å¤ãã³ãã©ã«ãããåããããã¨ãã§ãããããã§ã¯ function1,2,5 ã« __try/__except ãããã¯ãããã®ã§ãfunction5 ã®ä¾å¤ãã³ãã©ãå¦çã§ããªãã£ãå ´åã«ã¯ function2 ã®ä¾å¤ãã³ãã©ã«ãããåããããããã ããã¡ããé¢æ°ãæããã¨ãã«ã¯èªåã®æã£ã¦ãä¾å¤å¦çã¨ã³ããªãå¤ããä¸ã§æ¹ãã¦ã·ã¹ãã ã«ç»é²ãç´ãã
ãã®æ©æ§ã¯åç´ãªåé¢ãªã¹ã¯ãæ±ãã¦ãããã¹ã¿ãã¯ãªã¼ãã¼ããã¼ã§çãããå±éºã大ããã£ã (ä¾å¤ãã³ãã©ã«é¢ããæ
å ±ãã¹ã¿ãã¯ã«ç½®ãã®ã§ããããä¸æ¸ãããããªã¹ã¯ããã£ãã®ã ã) ãããåé¿ããããã«æ§ã
ãªä¿è·æ©æ§ãå¾ä»ãããã¦ãã£ãã(SafeSEH, SEHOP ãªã©ãå ã㦠ASLR ã¯ã¢ãã¬ã¹ãã©ã³ãã ã«é
ç½®ãããã¨ã§ SEH ä¿è·æ©æ§ã®å¹æãããªãé«ããã)
x64 ã®å ´å
ããããx64 Windows ã§ã¯æåããã»ãã¥ã¢ãªæ¹æ³è«ãæ¡ç¨ããã¦ãããã¡ããã¨ããã³ã³ãã¤ã©ã§åãåºãã x64 åã PE ãã¡ã¤ã«ã«ã¯ãåé¢æ°ã«é¢ãã unwind æ å ±ãä¿åããã¦ããã
- function 1 : rbp, rsi, rdi ãä¿å - function 2 : rbp ãä¿å; 24 ãã¤ãã®ãããã¡ãç¢ºä¿ - function 3 : rbp, xmm6, xmm7 ãç¹å®ç®æã«ä¿å; 136 ãã¤ãã®ãããã¡ãç¢ºä¿ - function 4 : rbp ãä¿å.... - function 5 : ....
ã®ããã«ããããä½ã«ä½¿ãã? å®å
¨ãªã³ã¼ã«ã¹ã¿ãã¯ã復å
ããããã§ããããã®æ¹æ³ã¯ DWARF2 Exception Handling ã®æ¹æ³è«ã«è¿ãã
ãã®å ´åã__try/__except å¥ã®ããé¢æ°ã§ç¹å¥ãªå¦ç (ã·ã¹ãã ã¸ã®ç»é²ã¨ç»é²è§£é¤ãªã©) ã¯è¡ãããªããããã«ããããã©ã¼ãã³ã¹ãåä¸ãããããã¦ä¾å¤çºçæã«ã¯ããã®ã¨ãã®ã¹ã¿ãã¯ããå
ã®ã³ã¼ã«ã¹ã¿ãã¯ã復å
ããä¸ã§ãæãè¿ãä¾å¤ãã³ãã©ãæ¢ãã¦å¼ã³åºãã(å¾®å¦ã«ã¾ã¡ãã£ã¦ããã©ã ãããã¯ãããªæãã)
- ä¾å¤çºçã¢ãã¬ã¹ (RIP) ãå¾ã
- RIP ã«å¯¾å¿ããé¢æ°ãåå¾ããã
- ãããåå¾ã§ããªãå ´åããããä¾ãã°ãé¢æ°ãã¹ã¿ãã¯ãä¸å使ç¨ãããä¾å¤ãã³ãã©ããªããããã¦ä¸åã®é¢æ°ãå¼ã³åºããªãå ´å (leaf function ã¨å¼ã°ãã) ã該å½ããã
- ãã®å ´åãæ»ãã¢ãã¬ã¹ (RIP) ã¯ç¾å¨ã®ã¹ã¿ãã¯ã¢ãã¬ã¹ã«åå¨ããã¨ä»®å®ãã2. ã«æ»ãã
- é¢æ°ãä¾å¤ãã³ãã©ãæã£ã¦ãã¦ããªãã㤠RIP ã PE ãã¡ã¤ã«ã§æå®ãããç¹å®ã®ç¯å²å
ã§ããã°ã対å¿ããä¾å¤ãã³ãã©ãå¼ã³åºãã
- ä¾å¤ãã³ãã©ãå¦çã§ããªãã£ãå ´åã¯æ¬¡ä»¥éã
- é¢æ°ã® unwind æ å ±ãå¾ãã
- unwind æ
å ±ã«æ ¼ç´ããã¦ãããããã¼ã°ã®ä½ç½®ãå¾ã¦ãé¢æ°ã®ãããã¼ã°ãã©ãããå¤å®ããã
- ä¸ã®ä¾ã§ãinsn ends at pc+0x ã¨ããã®ãã¾ãã«ãã®æ å ±ã
- ãããã¼ã°ãªãããã®ããã® unwind æ å ± (ãµãã»ãã) ãç®åºããã
- ãããã¯ãRIP ã«ç¶ãã³ã¼ãåãå¾ã¦ãéç解æã§é¢æ°ã®ã¨ããã¼ã°ãã©ãããå¤å®ããã
- é¢æ°ã¨ããã¼ã°ã¯ä¿åããæ å ±ã復å ãã¦ããæä¸ãªã®ã§ããããå¤å®ãããã¨ã¯å¿ é ã
- ãããæ£ããè¡ãããã«ãABI ã§é¢æ°ã®ã¨ããã¼ã°ã«ãããã³ã¼ãåã大ããå¶ç´ããã¦ããã®ã ã
- ã¨ããã¼ã°ãªãããã®ããã® unwind æ å ± (ãµãã»ãã) ãç®åºããã
- 対å¿ãã unwind æ å ±ãå ã«ãã¬ã¸ã¹ã¿ã (ä»®æ³çã«) 復å ããã
- é¢æ°ã®æ»ãã¢ãã¬ã¹ (RIP) ãåå¾ãã2. ã«æ»ãã
ãããã㯠x86 ã® SEH ã¨åæ§ã ããã®æ¹æ³è«ãåªãã¦ããã®ã¯ãä¾å¤ãã³ããªã³ã°ã«é¢ããå
¨ã¦ã®æ
å ±ã¯ PE ãã¡ã¤ã«ã®èªã¿åãå°ç¨é åã«æ ¼ç´ããã¦ãããããä¾å¤ãã³ããªã³ã°ãã¯ã©ããã³ã°ã®ããã« (ã»ã¨ãã©ã®å ´å) 使ç¨ã§ããªããªãã¨ããç¹ã ã
ãããæªãè¨ãã°ãx64 ã® SEH ã¯ãã¼ãã«ã«é ¼ãåã£ã¦ãããããã¯ãå½è©²ããã°ã©ã ä¸ã§ SEH ã使ããªãå ´åã§ãæãã§ããªãç¶æ³/ã¯ã©ãã·ã¥ãå¼ãèµ·ããå¯è½æ§ããããä¾ãã°ãunwind ãã¼ãã«ã¤ãã®ãã¤ããªãã unwind ãã¼ãã«ãªãã®ãã¤ããªãå¼ã°ããå ´åãSEH ã¯ç¶æ³ã«ãã£ã¦ã¯æ£å¸¸ã«åä½ããªãã
sample.exe â sample.dll ã¨å¼ã³åºãã®æä¸: ----------------------------------------------------------------- sample.exe (MSVC ã§ãã«ããå®è¡ [ä¾å¤ãã³ããªã³ã°ããã¦ãã]) â sample.dll (mingw-w64 ã§ãã«ããå®è¡ [SEH, unwind ã¨ãã«ãªã]) ----------------------------------------------------------------- âbeforeâafter sample.exe (ä¾å¤ãã³ããªã³ã°ããã¦ããã®ã«æ£å¸¸ã«å¼ã³åºããããã¯ã©ãã·ã¥) â sample.dll (ä¾å¤çºçâ)
ã¾ã x86 ã§ããã°å¼·å¶çã«ä¾å¤ãã³ãã©ãç»é²ãã¦ããã°ã¦ã¼ã¶ã®æå®ããåçãªãã³ãã©ãå®è¡ãããã¨ãã§ããããx64 ã§ã¯ãã®æ¹æ³ã¯åºæ¬çã«ãä¸å¯ãã§ããã*1代ããã« VEH (Vectored Exception Handling) ã¨å¼ã°ããæ©æ§ãããããã«ã¼ãã«ã¢ã¼ãã®ãã©ã¤ãã¯ãã® VEH ãå©ç¨ãããã¨ãã§ããªãã
(ä»ã¾ã§ã®) mingw-w64 ã¯ã¾ãã«ãã®æ¡ä»¶ã«å½ã¦ã¯ã¾ã£ã¦ãã¾ããunwind æ
å ±ãåãåºããã¨ãã§ãããå®å
¨ãªã«ã¼ãã«ã¢ã¼ããã©ã¤ããæ¸ãã«ã¯å°ã
å±ãªãæãã ã£ããSEH ã®ãã¼ã¯ã¼ãã§ãã __try/__except ã mingw-w64 ã® gcc ã¯è§£éãããx64 ã«ã¼ãã«ã¢ã¼ããã©ã¤ãã§ä¾å¤ã使ãã«ã¯ããã¯ãå¿
è¦ãªãã®ã ã¨æã£ã¦ãããåä»ã§ããã
mingw-w64 ã®é²æ©
ããããæè¿ã®ãã¼ã¸ã§ã³ã® mingw-w64 ã§ã¯ãã¡ããã¨é¢æ°ã® unwind æ å ±ãåãåºãããã«ãªã£ã¦ããã
$ x86_64-w64-mingw32-objdump -p a.exe | less -------------------------------------------------------------- // ãªã«ãããªã <main> é¢æ°ã® unwind æ å ± 000000000000606c: Flags: UNW_FLAG_NHANDLER. Entry has 3 codes. Prologue size: 8, Frame offset = 0x2. Frame register is rbp. At pc 0x0000000000401550 there are the following saves (in logical order). insn ends at pc+0x01: push rbp. insn ends at pc+0x08: save stack region of size 0x0000000000000020. insn ends at pc+0x08: FPReg = (FrameReg) + 0x0000000000000000.
ããã¯ãbinutils 㨠gcc (4.6 ç³»ã®ã¿) ã®åæ¹ã unwind æ å ±ããµãã¼ãããå¹æã§ãããã§ã¯ãreturn 0 ã®ã¿ãæ¸ããã·ã³ãã«ãª main é¢æ°ã®ã¢ã»ã³ããªåºåãè¦ã¦ã¿ããã
.globl main .def main; .scl 2; .type 32; .endef .seh_proc main main: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp subq $32, %rsp .seh_stackalloc 32 .seh_setframe %rbp, 32 .seh_endprologue call __main movl $0, %eax addq $32, %rsp popq %rbp ret .seh_endproc
ããã«ã.seh_ ã§å§ã¾ããã¼ã¯ã¼ããå¤æ°ä½¿ç¨ããã¦ãããã¨ã«æ°ã¥ãããããSEH é¢é£ã®æ
å ±ãåãåºãçä¼¼å½ä»¤ã as ããµãã¼ãããgcc ã¯ããã«åãããåºåãè¡ããld ã¯è¤æ°ãªãã¸ã§ã¯ãã® unwind æ
å ±ãçµ±åãããã¨ã§ããã®ãã㪠unwind æ
å ±ãåãåºããã¨ã«æåãã¦ããã®ã ã
ãããªãããã®ãã¤ããªããä¾å¤ãåé¡ãªãæµããã¨ãã§ããã(mingw-w64 ã§ä½æãããã¤ããªã«ãã£ã¦ä¾å¤ãã³ããªã³ã°ãæ»ããã¨ããªãã)
ãããããã㯠SEH ãã使ããããã¨ãæå³ããªããgcc ã¯æ¬æ¥ SEH ã®ããã® __try/__except ãã¼ã¯ã¼ãããµãã¼ããã¦ããããæè¿ã®ãã¼ã¸ã§ã³ã® mingw-w64 ã§ãã¨ã©ã¼ã¨ãªããã¨ãªãã¨ã«ã¼ãã«ã¢ã¼ãã§ã¯ä½¿ãããããªãâ¦ããæã£ããããã mingw-w64 ãåãåºãããã¤ããªã®æ
å ±ãè¦ã¦ããã¨ãèå³æ·±ããã¨ã«æ°ã¥ããã
$ x86_64-w64-mingw32-objdump -p a.exe | less -------------------------------------------------------------- // !? 000000000000602c: Flags: UNW_FLAG_EHANDLER. Entry has 1 codes. Prologue size: 4, Frame offset = 0x0. Frame register is none. At pc 0x0000000000401510 there are the following saves (in logical order). insn ends at pc+0x04: save stack region of size 0x0000000000000028. User data: 000: d0 28 00 00 01 00 00 00 1e 15 00 00 28 15 00 00 010: d0 19 00 00 28 15 00 00 000000000000604c: Flags: UNW_FLAG_EHANDLER. Entry has 1 codes. Prologue size: 4, Frame offset = 0x0. Frame register is none. At pc 0x0000000000401530 there are the following saves (in logical order). insn ends at pc+0x04: save stack region of size 0x0000000000000028. User data: 000: d0 28 00 00 01 00 00 00 3e 15 00 00 48 15 00 00 010: d0 19 00 00 48 15 00 00
ãªãã¨ï¼ mingw-w64 ã® objdump ã§ã¯ User data ã¨ã®ã¿è¨ããã¦ããããããã¯ç´ãããªãä¾å¤ãã³ãã©ã®æ å ±ã ã*2 gcc 㯠SEH ãã¼ã¯ã¼ãã使ããªãã®ã«ãªãã§ããã®ã? éã¢ã»ã³ããªã¨ç §åããã¨ããã® 2 ã¤ã®é¢æ°ã¯ WinMainCRTStartup 㨠mainCRTStartup ã ããã㯠mingw-w64 ã® CRT å ã«ç®æ¨ããããããªé°å²æ°ãã¨ããããã§ãmingw-w64-crt/crt ä¸ã® crtexe.c ãåç §ããã
/** mingw-w64 ã½ã¼ã¹ã³ã¼ãããå¼ç¨ã å½è©²é¨åã¯ãããªãã¯ãã¡ã¤ã³ã§ããã http://mingw-w64.svn.sourceforge.net/viewvc/mingw-w64/trunk/mingw-w64-crt/crt/crtexe.c http://mingw-w64.svn.sourceforge.net/viewvc/mingw-w64/trunk/mingw-w64-crt/crt/crtexe.c?view=log **/ int WinMainCRTStartup (void) { int ret = 255; #ifdef __SEH__ asm ("\t.l_startw:\n" "\t.seh_handler __C_specific_handler, @except\n" "\t.seh_handlerdata\n" "\t.long 1\n" "\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n" "\t.text" ); #endif /* (ä¸ç¥) */ #ifdef __SEH__ asm ("\t.l_endw: nop\n"); #endif return ret; }
èªããã°ç°¡åã ãå ã»ã©ã®ä¾ã¨åãã .seh_* ã¨ãããã¼ã¯ã¼ãããä»åº¦ã¯ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã¨ãã¦è¨è¿°ãã¦ããã(#ifdef ãå ¥ã£ã¦ããã®ã¯ãunwind æ å ±åºåããµãã¼ãããªãå¤ã mingw-w64 ã«å ãããã¼ãã«ãã¼ã¹ã® SEH ã§ã¯ãªã 32-bit çããµãã¼ãããããã) ãããããã㧠SEH ã®ä¾å¤ãã³ãã©ãè¨å®ãã¦ãããä¾å¤ããã¡ã㨠CRT ã«æ¸¡ãããããã«ãªã£ã¦ããã*3æå¾ã® nop ã¯ãã©ãã«ãæ£å¸¸ã«åãããããã®ããã¼ã ãããã¨ãªãã°ããã®ææ³ã使ãã°ã©ã®ãããªã¢ããªã±ã¼ã·ã§ã³ã§ãã£ã¦ããã®ããã®æ£å¸¸ãª SEH ãã¼ãã«ã®ãã¼ã¿ãæ§ç¯ã§ãããã¨ããããã§ããã£ã¦ã¿ããâ¦ã¢ã¬ãåããªã!?
mingw-w64 ã®ãã°
32-bit ã§ã¯ã©ãã·ã¥ããã®ã¯äºæãã¦ãã¢ã*4ã ãã©ã64-bit ã§ãã¯ã©ãã·ã¥ããã®ã¯äºæ³å¤ã ããã¨ããããã§ãWinDbg ãé§ä½¿ãã¦ãªãã¨ããã°çºè¦ã(ä¾å¤ãã³ãã©ã§ã¯ã½ããã¦ã§ã¢ãã¬ã¼ã¯ãã¤ã³ããç¡å¹ã«ãªããã¨ãç¥ããããããæéãé£ã£ãã) æ¨æ¥ mingw-w64 ããã¸ã§ã¯ãã«ããããæãã¦ãå³æ¥ã§ä¿®æ£ãããã
"\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n"
ãã㯠4 ã¤ã®ãã¤ã³ã¿ããã¼ã¿ã¨ãã¦åºåãã¦ãããããã®ãã©ã¼ãããã¯æ¬¡ã®ããã«ãªã£ã¦ããã*5
- BeginAddress
- __try ãããã¯ã®éå§ã¢ãã¬ã¹
- EndAddress
- __try ãããã¯ã®çµäºã¢ãã¬ã¹
- HandlerAddress
- ä¾å¤ãã£ã«ã¿ (é¢æ°ã¸ã® RVA)
- JumpTarget
- __except ãããã¯ã®ã¢ãã¬ã¹ (mingw-w64 ã«ããã¦ã¯æªä½¿ç¨)
ããã¦ãBeginAddress 㨠EndAddress ã®éã§ä¾å¤ãçºçãããªãã°ä¾å¤ãã£ã«ã¿ (ããã¦å¿ è¦ãªããã³ãã©) ãå¼ã³åºãâ¦ã®ã ãããã®å¤å®ã¯ã次㮠C ã³ã¼ãã«ã»ã¼çããã
if (target >= BeginAddress && target < EndAddress) /* catch exception */
ãããã.l_endw ç´å¾ã® nop å½ä»¤â¦ã®åã®å½ä»¤ã¯ call å½ä»¤ã§ãå®éã«ã¯ãã®æ»ãã¢ãã¬ã¹ã§ãã nop å½ä»¤ã®ã¢ãã¬ã¹ãå¤å®ã«ç¨ãããããããã nop å½ä»¤ã¯ .l_endw ã®å¾ã«ããããããã¬ã¼ã ãã¼ã¹ã®ä¾å¤ãã³ããªã³ã°ãæ£ããåãã¦ããªãã£ã*6ã(CRT ãä¾å¤ãå¥ã®æ段ã§ãã£ãããã¦ãããããä»ã¾ã§é¡å¨åããªãã£ãã ãã) ã¨ããããã§ã.l_endw 㨠.l_endw+1 ã«ç½®æãããã.l_endw ã©ãã«ã®åã« nop å½ä»¤ãæ¿å ¥ãããã®ã©ã¡ããã§ç´ãã(ããä¸æ¹ãåæ§ã«ä¿®æ£ããã) ä¿®æ£çã¯ãããªæãã(åè ã®ä¿®æ£ãé©ç¨ãããã®ã ããæ¬å®¶ã® mingw-w64 ã«ã¯å¾è ã®ããããæ¡ç¨ãããã)
/** mingw-w64 ã½ã¼ã¹ã³ã¼ããä¿®æ£ã å½è©²é¨åã¯ãããªãã¯ãã¡ã¤ã³ã§ããã http://mingw-w64.svn.sourceforge.net/viewvc/mingw-w64/trunk/mingw-w64-crt/crt/crtexe.c http://mingw-w64.svn.sourceforge.net/viewvc/mingw-w64/trunk/mingw-w64-crt/crt/crtexe.c?view=log **/ int WinMainCRTStartup (void) { int ret = 255; #ifdef __SEH__ asm ("\t.l_startw:\n" "\t.seh_handler __C_specific_handler, @except\n" "\t.seh_handlerdata\n" "\t.long 1\n" "\t.rva .l_startw, .l_endw+1, _gnu_exception_handler ,.l_endw+1\n" "\t.text" ); #endif /* (ä¸ç¥) */ #ifdef __SEH__ asm ("\t.l_endw: nop\n"); #endif return ret; }
ã¡ãªã¿ã«ãã㯠mingw-w64 æ¨æºã®ä¾å¤ãã³ããªã³ã°ããã¾ãåãããããã®ä¿®æ£ã ã⦠mingw-w64 æ¨æºã®ä¾å¤ãã£ã«ã¿ (_gnu_exception_handler) ã¯ãä¾å¤ã signal ã«å¤æããæ©è½ãæã¤ãsignal ã®ä½¿ãæ¹ãç¥ã£ã¦ãããªããLinux ã¨åãããã«ä¾å¤ããã³ãã«ãããã¨ãå¯è½ã ã(æ®å¿µãªãã sigaction*7 ã§ã¯ãªããã)
ã¨ãªãã°ãããã¨ã
ãã¦ãã§ã¯å¥ã®ãã¨ããã£ã¦ã¿ãããæ¬æ¥ã¯ x64 ã«ã¼ãã«ã¢ã¼ãã§ä¾å¤ãçºçããããµã³ãã«ãä½ãäºå®ã ã£ãããå®å ¨æ§ãæ¤è¨¼ããæéããªãã£ãã®ã§ä»£ããã« VMware ãæ¤åºãããµã³ãã«ãä½ã£ã¦ã¿ãããã®ç¶æ³ãªã signal ã使ããªãããªããããã¿çã«ã¯ãã¾ãé¢ç½ããªãã®ã§ãä»ã¯ç ã£ã¦ãã¦ãããã
#include <stdio.h> #include <stdlib.h> #include <windows.h> long CALLBACK detect_vmware_except( PEXCEPTION_POINTERS data ) { data->ContextRecord->Rbx = 0; data->ContextRecord->Rip += 1; return EXCEPTION_CONTINUE_EXECUTION; } __attribute__((noinline)) int detect_vmware(void) { DWORD result; __asm__ __volatile__ ( ".seh_handler __C_specific_handler, @except\n\t" ".seh_handlerdata\n\t" ".long 1\n\t" ".rva .l_vmdetect, .l_vmdetect+1, detect_vmware_except\n\t" ".long 0\n\t" ".text\n\t" "xorl %%ebx, %%ebx\n\t" "movl $0x564d5868, %%eax\n\t" "movl $10, %%ecx\n\t" "movw $0x5658, %%dx\n" ".l_vmdetect:\n\t" ".byte 0xed" /* in (%dx),%eax */ : "=b"(result) : : "%eax", "%ecx", "%edx", "cc", "memory" ); return result == 0x564d5868; } int main(int argc, char** argv) { if (detect_vmware()) { printf("VMware is detected!\n"); } else { printf("VMware is NOT detected.\n"); } return 0; }
VMware ã®æ¤åºã«ã¯ãããã¯ãã¢ãã¼ãã使ç¨ãã¦ãããããããããã§ä½¿ç¨ãã¦ãã in å½ä»¤ã¯ VMware ã®ç¡ãç°å¢ä¸ã§ã¯ä¾å¤ãçºçããã¦ãã¾ããããã§ããã®é¨åã§çºçããä¾å¤ããã£ããããé©åã«æ¡ãæ½°ãã¦ããã®ãä¸è¨ã®ãµã³ãã«ã ã64-bitãgcc 4.6 ãã¼ã¹ã® mingw-w64 ã§ã¯é©åã«åä½ãããããã§ã¯ããã«æ´ç·´ãããæ¡ãæ½°ãæ¹ãæ¡ç¨ãã¦ãããJumpTarget ã¯ããã¼ã® .long ã§é©å½ã«åãã¦ããã®ä¸ã§ in å½ä»¤ã® 1 ãã¤ãã ãã __try ãããã¯ã«ç¸å½ãããããªå®è£
ã«ãªã£ã¦ããã(end ã«ç¸å½ããã©ãã«ããªãã) ããã§ä¾å¤ãçºçããå ´åãin å½ä»¤ã ããã¹ããããããVMware ãæ¤åºãããªãã£ããã¨ã示ãããã¼ã®æ°åãå
¥ãããã¨ã§ãã¡ããã¨ãé VMwareãã®æ¤åºã«ãæåãã¦ããã®ã ã
ã¡ãªã¿ã«ã__attribute__ï¼ï¼noinlineï¼ï¼ ã¨æ¸ãã¦ããã®ã¯ãä¸å¿
è¦ãª (-O3 ãªã©ã®ãªãã·ã§ã³ã«ãã) ã¤ã³ã©ã¤ã³åãé²æ¢ããããã ãMS 製ã³ã³ãã¤ã©ãªã SEH ã®ã¨ã³ããªãé©åã«çæãã¦ãããããmingw-w64 ã§ã¯ã¾ã ããã¯ãããªããä¸ãä¸ã¤ã³ã©ã¤ã³åãããã¨ä¸å¿
è¦ãªè¡çªãå¼ãèµ·ããå¯è½æ§ããã (ä»åã®ã³ã¼ãã®å ´åã¯å¤ååé¡ãªããã©ã) ããããã®å±æ§ãä»ãã¦ã¤ã³ã©ã¤ã³åãé²æ¢ãã¦ããã
ã¾ã¨ã
ã¨ããããã§ãã©ãã ãã? 御ä¸è¾ã«ãæ´ç·´ãããã¨ã¯è¨ããªãå®è£ ã ããx64ãé MS ã³ã³ãã¤ã©ã§ãä¸å¿ SEH ãããã¢ã«ä½¿ããããã«ãªã£ã¦ãããããªããªãããããã©ã使ã?
*1:å ¨ãã§ããªãããã§ã¯ãªãã®ã ããããã¢ãªããã°ã©ã 㧠gs:0 ãå¼ãã¤ãã¯è¦ããã¨ããªãã
*2:ãã㯠objdump ãä¾å¤ãã³ãã©ã®ããã®æ å ±ã解éã§ããªããããå ãã¦ãé¢æ°ãã¼ãã«ã®ãã©ã°ã§ãã UNW_FLAG_EHANDLER ãããã®é¢æ°ãä¾å¤ãã³ãã©ãæã£ã¦ãããã¨ã示ãã¦ããã
*3:ã½ã¼ã¹ã³ã¼ãä¸ã® __C_specific_handler (msvcrt, ntdll, ntoskrnl ãªã©ãã·ã¹ãã ä¸ã®è¤æ°ã® DLL ã§å®ç¾©ããã¦ãã) ã¯ãã·ã¹ãã ãä¿æããããã©ã«ãã®ä¾å¤ãã³ãã©ã§ããã®ã«ã¼ãã³ã«ããåããã½ã¼ã¹ã³ã¼ãä¸ã«è¨è¿°ããã¦ãã _gnu_exception_handler ãå¼ã³åºããããã¨ã«ãªãããã®é¢æ°ã¯åºæ¬çã« POSIX 風㮠signal ãå¼ã³åºããããã«ãã£ã¦é©åã«å¦çãããªããã°ã¢ããªã±ã¼ã·ã§ã³ãå¼·å¶çµäºãããã
*4:32-bit ç mingw-w64-crt ã¯ãSetUnhandledExceptionFilter ã®ã¿ã使ã£ã¦ signal ãå®è£ ãã¦ããã®ã§ããããç½®ãæããã°ã¯ã©ãã·ã¥ãããã¨ã¯äºæ³ã§ããã
*5:ã¡ãªã¿ã«å½è©²é¨åã®ç´åã.long 1 ã¨ããã®ã¯ããã® 4 ã¤çµã® RVA ã§æ§æãããä¾å¤ãã³ãã©æ å ±ã®æ°ã§ããã
*6:ãããã off-by-one ã¨ã©ã¼ã®å¤ç¨®ã