ããã°ã©ãã³ã°ããã³ã³ã³ãã¥ãŒã¿ãŒãã¯ãããžã«ããããã·ã¹ãã ã³ãŒã«ããšããçšèªã¯ãã¢ããªã±ãŒã·ã§ã³ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ïŒOSïŒã®ã«ãŒãã«ãæäœããŠæäœãå®è¡ããããšãæããŸãã ãã®ãããªçžäºäœçšãäž»ãªçžäºäœçšã§ãããšããäºå®ã«ãããã·ã¹ãã ã³ãŒã«ã®ã€ã³ã¿ãŒã»ããã¯çµ±åã®æãéèŠãªæ®µéã§ãããšæãããŸãã OSã«ãŒãã«ã®éèŠãªã³ã³ããŒãã³ãã§ããã·ã¹ãã ã³ãŒã«ã€ã³ã¿ãŒãã§ã€ã¹ãå¶åŸ¡ã§ããŸããããã«ãããã«ãŒãã«ãµãŒãã¹ã«å¯Ÿããã¢ããªã±ãŒã·ã§ã³ãœãããŠã§ã¢ã®ãªã¯ãšã¹ããæ€æ»ã§ããŸãã
ãã®èšäºã¯ã課ããããã»ãã¥ãªãã£æ©èœã®å®è£
ãç¹ã«ãœãããŠã§ã¢ã·ã¹ãã ãžã®çµ±åã®ç¹å®ã®åé¡ã«åãããã
以åã«çºè¡šããããµã€ã¯ã«ã®ç¶ãã§ãã
I.ã¢ãããŒãã®åã蟌ã¿
Linuxã«ãŒãã«ãžã®ã·ã¹ãã ã³ãŒã«ãã€ã³ã¿ãŒã»ããããã«ã¯ãããŸããŸãªæ¹æ³ããããŸãã ãŸããåäžã®ã·ã¹ãã ã³ãŒã«ãã€ã³ã¿ãŒã»ããããããã«ãã«ãŒãã«é¢æ°ãã€ã³ã¿ãŒã»ãããã
以åã«æ€èšãããæ¹æ³ã䜿çšã§ããããšã«æ³šæãã䟡å€ããããŸãã å®éãã»ãšãã©ã®ã·ã¹ãã ã³ãŒã«ã¯å¯Ÿå¿ããé¢æ°ïŒ
sys_openãªã© ïŒã§è¡šããããããããããã€ã³ã¿ãŒã»ããããã¿ã¹ã¯ã¯ããããã®é¢æ°ãã€ã³ã¿ãŒã»ããããã¿ã¹ã¯ãšåçã§ãã ãã ããã€ã³ã¿ãŒã»ãããããã·ã¹ãã ã³ãŒã«ã®æ°ã®å¢å ãšãããžãã¹ããžãã¯ãã®è€éãã«ããããã®ã¢ãããŒãã¯å¶éãããå ŽåããããŸãã
ããæ®éçãªæ¹æ³ã¯ãã·ã¹ãã ã³ãŒã«ã®ããžãã¯ãå®è£
ããé¢æ°ãžã®ãã€ã³ã¿ãŒãå«ãã·ã¹ãã ã³ãŒã«ããŒãã«ã®ãšã³ããªãå€æŽããããšã§ãïŒä»¥äžã®è¡šãåç
§ïŒã ããŒãã«ã¯ããã³ãã©ãŒé¢æ°ãžã®ãã€ã³ã¿ãŒããåŸç¶ã®å®è¡ã§ã¢ããªã±ãŒã·ã§ã³ã«ãã£ãŠèŠæ±ãããã·ã¹ãã ã³ãŒã«ã®æ°ã«ãã£ãŠå¯Ÿå¿ããããŒãã«ããéžæããããšãã«ãã¹ã±ãžã¥ãŒãªã³ã°ã§ã«ãŒãã«ã«ãã£ãŠäœ¿çšãããŸãã ãã®ãããªãã€ã³ã¿ãŒã眮ãæãããšãã·ã¹ãã ã³ãŒã«ã®åŠçã«é¢ããŠã«ãŒãã«ã®ããžãã¯ãå€æŽã§ããŸãã ä»åŸããã®ã¡ãœããã®å®è£
ãæåãããã«ã¯ãããŒãã«èªäœãäœããã®æ¹æ³ã§èŠã€ããå¿
èŠãããããšã«æ³šæããŠãã ããã ãããã¯ãšã¯ã¹ããŒããããŸããã æçµçã«ãã·ã¹ãã ã³ãŒã«ã®ã€ã³ã¿ãŒã»ããã¯ãåã«ããŒãã«èŠçŽ ããªãŒããŒã©ã€ãããããšã§æ§æãããŸãã
ã·ã¹ãã ã³ãŒã«ãã€ã³ã¿ãŒã»ããããæãæ®éçãªæ¹æ³ã¯ãã·ã¹ãã ã³ãŒã«ãããŒãžã£ã³ãŒãã®å€æŽã§ãããã·ã¹ãã ãµãŒãã¹ãèŠæ±ããã¹ã¬ããã®ã³ã³ããã¹ãã®ååŠçãšåŸåŠçãæäŸãããããã«å€æŽããããŸãŸã§ãã ãã®ãªãã·ã§ã³ã¯ã以åã®ãªãã·ã§ã³ãšæ¯èŒããŠæè»æ§ãé«ããŸãã ãã³ãã©ãŒé¢æ°ã®ååŸã«ç¶æ
ç£èŠã®åäžãã€ã³ããå°å
¥ããŸãã
次ã«ããã£ã¹ãããã£ã³ãŒããå€æŽããŠLinuxã«ãŒãã«ã·ã¹ãã ã³ãŒã«ãã€ã³ã¿ãŒãã§ã€ã¹ã«åã蟌ãæ¹æ³ã®
äŸã詳现ã«èª¬æããŸãã
IIã Linuxã«ãŒãã«ã§ã®ã·ã¹ãã ã³ãŒã«ã®ãã£ã¹ããã
ã·ã¹ãã ã³ãŒã«ã®ãã£ã¹ãããã¯å€ãã®ãã¥ã¢ã³ã¹ãæã€ããªãè€éãªããã»ã¹ã§ããããã£ã¹ãããããã»ã¹èªäœïŒã·ã¹ãã ã³ãŒã«ã«å¯Ÿå¿ããé¢æ°ã®ãã§ãããšå®è¡ïŒãé€ããŠãå®è£
ã«ã€ããŠä»ã«äœãç¥ãå¿
èŠããªãããããã®èšäºã®ãã¬ãŒã ã¯ãŒã¯ã§ã¯å€ãã®è©³çŽ°ãçç¥ããŸãã
åŸæ¥ãLinuxã«ãŒãã«ã¯ãx86ã¢ãŒããã¯ãã£åãã«æ¬¡ã®ã·ã¹ãã ã³ãŒã«æ©èœããµããŒãããŠããŸãã
- INT 80håœä»€ïŒ32ãããã€ã³ã¿ãŒãã§ã€ã¹ããã€ãã£ãã³ãŒã«ãŸãã¯ãšãã¥ã¬ãŒã·ã§ã³ïŒ;
- SYSENTERåœä»€ïŒ32ãããã€ã³ã¿ãŒãã§ã€ã¹ããã€ãã£ãã³ãŒã«ãŸãã¯ãšãã¥ã¬ãŒã·ã§ã³ïŒ;
- SYSCALLåœä»€ïŒ64ãããã€ã³ã¿ãŒãã§ã€ã¹ããã€ãã£ãã³ãŒã«ãŸãã¯ãšãã¥ã¬ãŒã·ã§ã³ïŒã
以äžã¯ã䜿çšãããªãã·ã§ã³
ã«å¿ããŠãç§ã
åããã·ã¹ãã ã³ãŒã«ã®åªããäŸã§ãã

ã芧ã®ãšããã32ãããã¢ããªã±ãŒã·ã§ã³ã¯INT 80hããã³SYSENTERã¡ã«ããºã ã䜿çšããŠã·ã¹ãã ã³ãŒã«ãè¡ãã64ãããã¢ããªã±ãŒã·ã§ã³ã¯SYSCALLã䜿çšããŸãã åæã«ã64ãããç°å¢ã§32ãããã³ãŒããå®è¡ããæ©èœã®ãµããŒãããããŸãïŒããããäºæã¢ãŒã-ãšãã¥ã¬ãŒã·ã§ã³/äºæã¢ãŒã;ã«ãŒãã«ãªãã·ã§ã³
CONFIG_IA32_EMULATION
ïŒã ãã®ç¹ã«é¢ããŠãã«ãŒãã«ã«ã¯
sys_call_table
ãš
ia32_sys_call_table
ïŒãšãã¥ã¬ãŒã·ã§ã³ã¢ãŒãã§ã®ã¿äœ¿çšå¯èœïŒã®2ã€ã®ãšã¯ã¹ããŒãäžå¯èœãªããŒãã«ããããã·ã¹ãã ã³ãŒã«ãåŠçããé¢æ°ã®ã¢ãã¬ã¹ãå«ãŸããŠããŸãã
äžè¬çãªã±ãŒã¹ã§ã¯ãå¯èœãªãã¹ãŠã®ã¡ã«ããºã ã64ãããã«ãŒãã«ã§è¡šãããå Žåã察å¿ãããã£ã¹ãããã£ãŒã®ããžãã¯ã決å®ãã4ã€ã®ãšã³ããªãã€ã³ãããããŸãã
- ãšãã¥ã¬ãŒã·ã§ã³INT 80hã ia32_syscall ïŒx86 / ia32 / ia32entry.SïŒ;
- SYSENTERãšãã¥ã¬ãŒã·ã§ã³ã ia32_sysenter_target ïŒx86 / ia32 / ia32entry.SïŒ;
- SYSCALL32ãšãã¥ã¬ãŒã·ã§ã³ã ia32_cstar_target ïŒx86 / ia32 / ia32entry.SïŒ;
- SYSCALLã system_call ïŒx86 /ã«ãŒãã«/ entry_64.SïŒã
äœããã®æ¹æ³ã§ãã¢ããªã±ãŒã·ã§ã³ãã·ã¹ãã ã³ãŒã«ãè¡ããšãã«ãŒãã«ãå¶åŸ¡ãååŸããŸãã èæ
®ãããåã±ãŒã¹ã®ã·ã¹ãã ã³ãŒã«ãããŒãžã£ã¯ä»ã®ã±ãŒã¹ãšã¯ç°ãªããŸãããäžè¬æ§ã倱ãããšãªãã
system_callã®äŸã䜿çšããŠäžè¬çãªæ§é ãæ€èšã§ããŸãã
0xffffffff81731670 <+0>: swapgs 0xffffffff81731673 <+3>: mov %rsp,%gs:0xc000 0xffffffff8173167c <+12>: mov %gs:0xc830,%rsp 0xffffffff81731685 <+21>: sti 0xffffffff81731686 <+22>: data32 data32 xchg %ax,%ax 0xffffffff8173168a <+26>: data32 xchg %ax,%ax 0xffffffff8173168d <+29>: sub $0x50,%rsp 0xffffffff81731691 <+33>: mov %rdi,0x40(%rsp) 0xffffffff81731696 <+38>: mov %rsi,0x38(%rsp) 0xffffffff8173169b <+43>: mov %rdx,0x30(%rsp) 0xffffffff817316a0 <+48>: mov %rax,0x20(%rsp) 0xffffffff817316a5 <+53>: mov %r8,0x18(%rsp) 0xffffffff817316aa <+58>: mov %r9,0x10(%rsp) 0xffffffff817316af <+63>: mov %r10,0x8(%rsp) 0xffffffff817316b4 <+68>: mov %r11,(%rsp) 0xffffffff817316b8 <+72>: mov %rax,0x48(%rsp) 0xffffffff817316bd <+77>: mov %rcx,0x50(%rsp) 0xffffffff817316c2 <+82>: testl $0x100801d1,-0x1f78(%rsp) 0xffffffff817316cd <+93>: jne 0xffffffff8173181e <tracesys> 0xffffffff817316d3 <+0>: and $0xbfffffff,%eax 0xffffffff817316d8 <+5>: cmp $0x220,%eax 0xffffffff817316dd <+10>: ja 0xffffffff817317a5 <badsys> 0xffffffff817316e3 <+16>: mov %r10,%rcx 0xffffffff817316e6 <+19>: callq *-0x7e7fec00(,%rax,8) 0xffffffff817316ed <+26>: mov %rax,0x20(%rsp) 0xffffffff817316f2 <+0>: mov $0x1008feff,%edi 0xffffffff817316f7 <+0>: cli 0xffffffff817316f8 <+1>: data32 data32 xchg %ax,%ax 0xffffffff817316fc <+5>: data32 xchg %ax,%ax 0xffffffff817316ff <+8>: mov -0x1f78(%rsp),%edx 0xffffffff81731706 <+15>: and %edi,%edx 0xffffffff81731708 <+17>: jne 0xffffffff81731745 <sysret_careful> 0xffffffff8173170a <+19>: mov 0x50(%rsp),%rcx 0xffffffff8173170f <+24>: mov (%rsp),%r11 0xffffffff81731713 <+28>: mov 0x8(%rsp),%r10 0xffffffff81731718 <+33>: mov 0x10(%rsp),%r9 0xffffffff8173171d <+38>: mov 0x18(%rsp),%r8 0xffffffff81731722 <+43>: mov 0x20(%rsp),%rax 0xffffffff81731727 <+48>: mov 0x30(%rsp),%rdx 0xffffffff8173172c <+53>: mov 0x38(%rsp),%rsi 0xffffffff81731731 <+58>: mov 0x40(%rsp),%rdi 0xffffffff81731736 <+63>: mov %gs:0xc000,%rsp 0xffffffff8173173f <+72>: swapgs 0xffffffff81731742 <+75>: sysretq
ã芧ã®ãšãããæåã®åœä»€ïŒ
swapgs
ïŒã¯ããŒã¿æ§é ãïŒãŠãŒã¶ãŒãã
swapgs
ïŒåãæ¿ããŸãã 次ã«ãã¹ã¿ãã¯ãæ§æãããå²ã蟌ã¿ãèš±å¯ãããåŠçäžã«å¿
èŠãªã¬ãžã¹ã¿ãããŒã³ã³ããã¹ãïŒ
pt_regs
æ§é äœïŒãã¹ã¿ãã¯äžã«åœ¢æãããŸãã äžèšã®ãªã¹ãã«æ»ã£ãŠã次ã®ã³ãã³ãã«ç¹å¥ãªæ³šæãæãå¿
èŠããããŸãã
0xffffffff817316d8 <+5>: cmp $0x220,%eax 0xffffffff817316dd <+10>: ja 0xffffffff817317a5 <badsys> 0xffffffff817316e3 <+16>: mov %r10,%rcx 0xffffffff817316e6 <+19>: callq *-0x7e7fec00(,%rax,8) 0xffffffff817316ed <+26>: mov %rax,0x20(%rsp)
æåã®è¡ã¯ãèŠæ±ãããã·ã¹ãã ã³ãŒã«çªå·ïŒã¬ãžã¹ã¿
%rax
ïŒ
%rax
æ倧蚱容å€ïŒ
__NR_syscall_max
ïŒãš
%rax
ãã©ããã確èªããŸãã æ€èšŒãæåããå Žåãã·ã¹ãã ã³ãŒã«ããã£ã¹ããããããŸããã€ãŸããã³ã³ãããŒã«ã¯å¯Ÿå¿ããããžãã¯ãå®è£
ããé¢æ°ã«ç§»åããŸãã
ãããã£ãŠãã·ã¹ãã ã³ãŒã«ãåŠçããããã»ã¹ã®ããŒãã€ã³ãã¯ãã£ã¹ãããã³ãã³ãã§ãããããã¯é¢æ°
call *sys_call_table(,%rax,8)
ïŒ
call *sys_call_table(,%rax,8)
ïŒã§ãã ãã®ã³ãã³ããå€æŽããŠãããã«åã蟌ã¿ãå®è¡ããŸãã
IIIã åã蟌ã¿æ¹æ³
åè¿°ã®ããã«ããã£ã¹ãããã£ã«åã蟌ãæ®éçãªæ¹æ³ã¯ãã·ã¹ãã ã³ãŒã«ïŒåŠçïŒã®ããžãã¯ãå®è£
ããæ©èœãå®è¡ããåãããã³ãã®å®è¡ïŒåŸåŠçïŒã®æ©èœãå®è¡ããåã«ãã¹ã¬ããã®ã³ã³ããã¹ããå¶åŸ¡ããæ©èœãæäŸããããã«ã³ãŒããå€æŽããããšã§ãã
説æããæ¹æ³ã§åã蟌ã¿ãå®è£
ããã«ã¯ããã£ã¹ãããã³ãã³ããå€æŽããŠïŒ
call *sys_call_table(,%rax,8)
ïŒãã£ã¹ãããã£ããããã«ããããããã®äžã«ç¡æ¡ä»¶ãžã£ã³ãã³ãã³ãïŒ
JMP REL32
ïŒã
service_stub
ãã³ãã©ã«æžã蟌ãããšãã
JMP REL32
ãŸãã ãã®å Žåããã®ãããªãã³ãã©ãŒã®äžè¬çãªæ§é ã¯æ¬¡ã®ããã«ãªããŸãïŒä»¥äžãæ¬äŒŒã³ãŒããšåŒã³ãŸãïŒã
system_call: swapgs .. jmp service_stub mov %rax,0x20(%rsp) ... swapgs sysretq service_stub: ... call ServiceTraceEnter ... call sys_call_table[N](args) ... call ServiceTraceLeave(regs) ... jmp back
ããã§ã
ServiceTraceEnter()
ãš
ServiceTraceLeave()
ã¯ãããããååŠçé¢æ°ãšåŸåŠçé¢æ°ã§ãã ãããã®ãã©ã¡ãŒã¿ãŒã¯ãã¹ããªãŒã ã®ã³ã³ããã¹ããè¡šãã¬ãžã¹ã¿ãŒæ§é ã§ãã
pt_regs
ãžã®ãã€ã³ã¿ãŒã§ãã æåŸã®åœä»€ã¯ããã®ãã³ãã©ãŒã®åŒã³åºãã以åã«è¡ãããå Žæãããã·ã¹ãã åŒã³åºããã£ã¹ãããã£ãŒã³ãŒãã«å¶åŸ¡ã移ãã³ãã³ãã§ãã
以äžã¯ã
system_call
ïŒSYSCALLåœä»€ïŒãã€ã³ã¿ãŒã»ããããããã®äŸãšããŠäœ¿çšããã
service_syscall64ãã³ãã©ãŒã³ãŒãã§ãã
.global service_syscall64 service_syscall64: SAVE_REST movq %rsp, %rdi call ServiceTraceEnter RESTORE_REST LOAD_ARGS 0 movq %r10, %rcx movq ORIG_RAX - ARGOFFSET(%rsp), %rax call *0x00000000(,%rax,8)
ã芧ã®ããã«ãäžèšã®æ§é ãæã£ãŠããŸãã ãã€ã³ã¿ãŒãšãªãã»ããã®æ£ç¢ºãªå€ã¯ãã¢ãžã¥ãŒã«ã®ããŒãããã»ã¹äžã«æ§æãããŸãïŒããã«ã€ããŠã¯åŸã§èª¬æããŸãïŒã ããã«ãäžèšã®ãã©ã°ã¡ã³ãã«ã¯è¿œå ã®èŠçŽ ïŒ
SAVE_REST
ã
RESTORE_REST
ã
LOAD_ARGS
ïŒãå«ãŸããŠããŸãããã®ç®çã¯ãäž»ã«
ServiceTraceEnter
ããã³
ServiceTraceLeave
åŒã³åºãåã«ã¹ããªãŒã ã®ã³ã³ããã¹ãïŒ
pt_regs
ïŒã
ServiceTraceLeave
ã§ãã
IVã åã蟌ã¿ã®æ©èœ
äœããã®æ¹æ³ã§Linuxã«ãŒãã«ã®ã·ã¹ãã ã³ãŒã«ã®ã¹ã±ãžã¥ãŒãªã³ã°ã¡ã«ããºã ã«çµ±åãå®è£
ãããšã次ã®å®éçãªåé¡ã解決ããå¿
èŠããããŸãã
- ã·ã¹ãã ã³ãŒã«ã®ãã£ã¹ãããã£ã®ã¢ãã¬ã¹ã®å®çŸ©ã
- ã·ã¹ãã ã³ãŒã«ã®ãã£ã¹ãããããŒãã«ã®ã¢ãã¬ã¹ã®æ±ºå®ã
- ãã£ã¹ãããã£ã³ãŒãã®å€æŽã
- ãã³ãã©ãŒã®ã«ã¹ã¿ãã€ãºã
- ã¢ãžã¥ãŒã«ãã¢ã³ããŒãããŸãã
ã·ã¹ãã ã³ãŒã«ãã£ã¹ãããã£ã®ã¢ãã¬ã¹ã®å®çŸ©ã·ã¹ãã ã«è€æ°ã®ãã£ã¹ãããã£ãååšããããšã¯ãã¢ãã¬ã¹ã決å®ããå¿
èŠãããããšãæå³ããŸãã äžèšã®ããã«ãåãã£ã¹ãããã£ã¯ãã·ã¹ãã ã³ãŒã«ãèŠæ±ããç¬èªã®ãã¡ãœãããã«å¯Ÿå¿ããŠããããšã«æ³šæããŠãã ããã ãããã£ãŠãé©åãªã¡ã«ããºã ã䜿çšããŠãå¿
èŠãªã¢ãã¬ã¹ã決å®ããŸãã
- INT 80hãIDTããŒãã«ãã¯ãã«ã®èªã¿åãïŒ è©³çŽ° ïŒã
- SYSENTERãçªå·MSR_IA32_SYSENTER_EIPïŒ more ïŒã®MSRã¬ãžã¹ã¿ã®å
容ãèªã¿åããŸãã
- SYSCALL32ãçªå·MSR_CSTARïŒ more ïŒã®MSRã¬ãžã¹ã¿ã®å
容ãèªã¿åããŸãã
- SYSCALLãçªå·MSR_LSTARïŒ more ïŒã®MSRã¬ãžã¹ã¿ã®å
容ãèªã¿åããŸãã
ãããã£ãŠãå¿
èŠãªã¢ãã¬ã¹ã¯ããããç°¡åã«æ±ºå®ãããŸãã
ã·ã¹ãã ã³ãŒã«ãã£ã¹ãããããŒãã«ã®ã¢ãã¬ã¹ã®æ±ºå®äžèšã®ããã«ã
sys_call_table
ããã³
ia32_sys_call_table
ãšã¯ã¹ããŒãã
ia32_sys_call_table
ãŸããã ã¢ãã¬ã¹ã決å®ããã«ã¯ããŸããŸãªæ¹æ³ããããŸãããåã®ã¹ãããã§ãã£ã¹ãããã£ã®ã¢ãã¬ã¹ã決å®ãããšãããŒãã«
call sys_call_table[N]
ãšãã圢åŒã®ãã£ã¹ãããåœä»€ãæ€çŽ¢ããã ãã§æ±ºå®ãããŸãã
ãããã®ç®çã®ããã«ãé
ã¢ã»ã³ãã©ãŒ ïŒ
udis86 ïŒã䜿çšããã®ãåççã§ãã æåã®åœä»€ããé ã«åœä»€ãé çªã«ãœãŒãããããšã«ãããç®çã®ã³ãã³ãã«å°éã§ããŸãããã®ã³ãã³ãã®åŒæ°ã¯å¯Ÿå¿ããããŒãã«ã®ã¢ãã¬ã¹ã«ãªããŸãã ãã£ã¹ãããã£ãŒã®æ§é ãååã«ç¢ºç«ãããŠãããšããäºå®ã«ãããç®çã®ã³ãã³ãïŒé·ã7ãã€ãã®CALLïŒã®ç¹æ§ãæ確ã«æ±ºå®ããé«åºŠãªä¿¡é Œæ§ã§å¿
èŠãªããŒãã«ã¢ãã¬ã¹å€ãååŸããããšãã§ããŸãã
äœããã®çç±ã§ããã§ååã§ãªãå Žåã¯ãåä¿¡ããã¢ãã¬ã¹ã®æ€èšŒã匷åã§ããŸãã ãããè¡ãã«ã¯ãããšãã°ãææ¡ãããããŒãã«ã®çªå·
__NR_open
æã€ã»ã«ã®å€ãsys_opené¢æ°ã®ã¢ãã¬ã¹ãšçãããã©ããã確èªã§ããŸãã ãã ãããã®äŸã§ã¯ããã®ãããªè¿œå ã®ãã§ãã¯ã¯å®è¡ãããŸããã
ãã£ã¹ãããã£ã³ãŒãã®å€æŽã·ã¹ãã ã³ãŒã«ãã£ã¹ãããã£ã®ã³ãŒããå€æŽããå Žåãã³ãŒããèªã¿åãå°çšïŒReadOnlyïŒã§ããããšãèæ
®ããå¿
èŠããããŸãã ããã«ãåäœäžã®ã·ã¹ãã ã§ã®ã³ãŒãå€æŽã¯ã¢ãããã¯ã§ããå¿
èŠããããŸã ãã®ãããå€æŽããã»ã¹äžã«ãã¹ã¬ããã®ãããããéšåçã«å®äºããã¬ã³ãŒããèŠããšãã«ãæªå®çŸ©ã®ç¶æ
ã¯ãããŸããã
ååã®
èšäºã§ã¯ãäžæ衚瀺ã®äœæã䜿çšããŠæžã蟌ã¿ä¿è·ãããããŒãžã«æžã蟌ãæ£ããæ¹æ³ã«ã€ããŠèª¬æããŸããã ããã§äœããç¹°ãè¿ãå¿
èŠã¯ãããŸããã ååæ§ã«é¢ããŠã¯ããã®åé¡ã¯æ žã®æ©èœã®ååã®ãããã¯ãæ€èšãã
ããšãã«
以åã«è°è«ãããŸããã
ãããã£ãŠãäžæç
ãªãããã³ã°ãšLinuxã«ãŒãã«ã®ç¹å¥ãªã€ã³ã¿ãŒãã§ãŒã¹
stop_machine
ã䜿çšããŠãæžã蟌ã¿ä¿è·ãããã³ãŒããå€æŽããããšããå§ãããŸãã
ãã³ãã©ãŒã®æ§ææ瀺ãããåã蟌ã¿æ¹æ³ã«åŸã£ãŠã7ãã€ãã®ãã£ã¹ãããã³ãã³ã
CALL MEM32
ã察å¿ãã
JMP REL32
ãã³ãã©ãŒãžã®5ãã€ãã®ç¡æ¡ä»¶ãžã£ã³ãã³ãã³ãã«çœ®ãæããããããã«ãåãã£ã¹ãããã£ãŒã®ã³ãŒããå€æŽãããŸãã ãã®çµæã移è¡ã®ç¯å²ã«ç¹å®ã®å¶éã課ããããŸãã ãã³ãã©ãŒã¯ã
JMP REL32
å Žæãã±2 GB以å
ã«é
眮ããå¿
èŠããããŸãã
ãã³ãã©ãŒã®æ§é ã«å¿ããŠãæ£ç¢ºãªåŒæ°ãæå®ããå¿
èŠãããã³ãã³ãïŒJMPããã³CALLïŒãå«ãŸããŠããŸãïŒããšãã°ãã¢ãã¬ã¹ãŸãã¯ã·ã¹ãã ã³ãŒã«ããŒãã«ã®ã¢ãã¬ã¹ãè¿ãïŒã ãã®ãããªå€ã¯ãã¢ãžã¥ãŒã«ã®ã³ã³ãã€ã«ãŸãã¯ããŒãã®æ®µéã§ã¯å©çšã§ããªããããããŒãåŸãäœæ¥ãââéå§ããåã«ãæåãã§ä»å ããå¿
èŠããããŸãã
ãã³ãã©ãŒãèšå®ããéã®ãã1ã€ã®éèŠãªæ©èœã¯ãã·ã¹ãã ã®æ£åžžæ§ãç¶æããªããã¢ãžã¥ãŒã«ãã¢ã³ããŒãã§ããããã«ããå¿
èŠãããããšã§ãã ãããã®ç®çã®ããã«ãã¡ã€ã³ã¢ãžã¥ãŒã«ãã¢ã³ããŒãããåŸã§ãããã³ãã©ã³ãŒãã¯ã·ã¹ãã ã«æ®ã£ãŠããå¿
èŠããããŸãïŒããã«ã€ããŠã¯åŸã§èª¬æããŸãïŒã
ã¢ãžã¥ãŒã«ãã¢ã³ããŒãããã·ã¹ãã ã®ã¡ã³ããã³ã¹äžã«ã¢ãžã¥ãŒã«ã®ã¢ã³ããŒããå®è¡ããå¿
èŠããããŸãã ããã¯ãã¢ãžã¥ãŒã«ãã¢ã³ããŒããããåŸãã·ã¹ãã ãæ£åžžã«æ©èœããããšãæå³ããŸãã ãã®ã¿ã¹ã¯ã¯ãã¢ãžã¥ãŒã«ã®ã¢ã³ããŒãã«ãããã¢ãžã¥ãŒã«ã§äœ¿çšããããã¹ãŠã®ã³ãŒããã¢ã³ããŒãããããããç°¡åã§ã¯ãããŸããã
ããšãã°ãã·ã¹ãã ã³ãŒã«ãè¡ãã¹ã¬ãããã«ãŒãã«å
ã§ã¹ãªãŒãç¶æ
ã«ãªãç¶æ³ãæ³åã§ããŸãã 圌ãç®èŠããç¬éãŸã§ã誰ããã¢ãžã¥ãŒã«ãã¢ã³ããŒãããããšããŸãã ååãšããŠãã·ã¹ãã ããããè¡ãããšã劚ãããã®ã¯ãããŸããã ãã®çµæãåé¡ã®ã¹ã¬ããããŠã§ã€ã¯ã¢ããããèŠæ±ãããã·ã¹ãã ã³ãŒã«ãå®äºãããšãå¶åŸ¡ã¯é©åãªãã³ãã©ã«æ»ããŸãïŒãã®ãããã¢ã³ããŒãããªãã§ãã ããïŒã
ãã ããã¢ãžã¥ãŒã«ã®ã¢ã³ããŒãåŸã«ã·ã¹ãã ã®æäœæ§ãç¶æããããã®æ¡ä»¶ã¯ããã³ãã©ãŒã®ã³ãŒããã¢ã³ããŒãããªãããšã ãã§ã¯ãããŸããã ãã³ãã©ãŒå
ã®å®éã®ã·ã¹ãã ã³ãŒã«ã¯ã
ServiceTraceEnterããã³
ServiceTraceLeaveãã¬ãŒã¹é¢æ°ãžã®2ã3ã®åŒã³åºãã§ãã©ãããããããã®ã³ãŒãã¯ã¢ã³ããŒããããã¢ãžã¥ãŒã«ã«ãã£ãããšã
æãåºããŠ
ãã ãã ã
ãããã£ãŠãã·ã¹ãã ã³ãŒã«ããæ»ããšãã«ãã¹ã¬ãããç©ççã«ååšããªãé¢æ°ãåŒã³åºãããšããç¶æ³ã«é¥ããªãããã«ããããã«ãåãã³ãã©ãŒã®ã³ãŒããç¹°ãè¿ãå€æŽããããããç¡å¹ãªåŒã³åºããæé€ããå¿
èŠããããŸãïŒã€ãŸããNOPã§ããããè©°ãŸãããŸãïŒã
V.ã«ãŒãã«ã¢ãžã¥ãŒã«ã®å®è£
ã®æ©èœ
次ã«ãLinuxã«ãŒãã«ã«ãŒãã«ã·ã¹ãã ã³ãŒã«ãã£ã¹ãããã¡ã«ããºã ãå®è£
ããã«ãŒãã«ã¢ãžã¥ãŒã«ã®æ§é ã«ã€ããŠèª¬æããŸãã
ã¢ãžã¥ãŒã«ã®äž»èŠãªæ§é ã¯
struct scentryã§ããããã¯ã察å¿ãããã£ã¹ãããã£ãŒã«åã蟌ãããã«å¿
èŠãªæ
å ±ãå«ãæ§é ã§ãã æ§é ã«ã¯æ¬¡ã®ãã£ãŒã«ããå«ãŸããŸãã
typedef struct scentry { const char *name; const void *entry; const void *table; const void *pcall; void *pcall_map; void *stub; const void *handler; void (*prepare)(struct scentry *); void (*implant)(struct scentry *); void (*restore)(struct scentry *); void (*cleanup)(struct scentry *); } scentry_t;
æ§é ã¯ãã©ã®ãã©ã¡ãŒã¿ãŒãã©ã®ããã«åã蟌ããã決å®ãã
é
åã«çµåãããŸãã
scentry_t elist[] = { ... { .name = "system_call", .handler = service_syscall64, .prepare = prepare_syscall64_1 }, { .name = "system_call", .handler = service_syscall64, .prepare = prepare_syscall64_2 }, ... };
æå®ããããã£ãŒã«ããé€ããæ§é ã®æ®ãã®èŠçŽ ã¯èªåçã«å
¥åãããŸã-ããã¯
prepare
æ©èœãæ
åœããŸãã 以äžã¯ãSYSCALLã³ãã³ãã®ãã£ã¹ãããã£ãžã®åã蟌ã¿ãæºåããé¢æ°ã®å®è£
äŸã§ãã
extern void service_syscall64(void); static void prepare_syscall64_1(scentry_t *se) { se->entry = get_symbol_address(se->name); se->entry = se->entry ? se->entry : to_ptr(x86_get_msr(MSR_LSTAR)); if (!se->entry) return; se->pcall = ud_find_insn(se->entry, 512, UD_Icall, 7); if (!se->pcall) return; se->table = to_ptr(*(int *)(se->pcall + 3)); }
ã芧ã®ãšããããŸããã·ã³ãã«åãããã«å¯Ÿå¿ããã¢ãã¬ã¹ã«è§£æ±ºããããšããŸãïŒ
se->entry
ïŒã ãã®æ¹æ³ã§ã¢ãã¬ã¹ã決å®ã§ããªãå Žåãåãã£ã¹ãããã£ã«åºæã®ã¡ã«ããºã ãæ©èœããŸãïŒãã®å Žåãçªå·MSR_LSTARã®MSRã¬ãžã¹ã¿ãèªã¿åããŸãïŒã
次ã«ãèŠã€ãã£ããã£ã¹ãããã£ã«ã€ããŠããã£ã¹ãããã³ãã³ããæ€çŽ¢ããïŒ
se->pcall
ïŒãæåãããšããã£ã¹ãããã£ã䜿çšããã·ã¹ãã ã³ãŒã«ããŒãã«ã®ã¢ãã¬ã¹ã決å®ãããŸãã
æºåãã§ãŒãºã®å®äºã¯ãä¿®æ£åŸã«ãã£ã¹ãããã£ã䜿çšãããã³ãã©ã³ãŒãã®äœæã§ãã 以äžã¯ããããè¡ã
stub_fixupé¢æ°ã§ãã
static void fixup_stub(scentry_t *se) { ud_t ud; memset(se->stub, 0x90, STUB_SIZE); ud_initialize(&ud, BITS_PER_LONG, \ UD_VENDOR_ANY, se->handler, STUB_SIZE); while (ud_disassemble(&ud)) { void *insn = se->stub + ud_insn_off(&ud); const void *orig_insn = se->handler + ud_insn_off(&ud); memcpy(insn, orig_insn, ud_insn_len(&ud)); if (ud.mnemonic == UD_Icall && ud_insn_len(&ud) == 7) { x86_insert_call(insn, NULL, se->table, 7); continue; } if (ud.mnemonic == UD_Icall && ud_insn_len(&ud) == 5) { x86_insert_call(insn, insn, orig_insn + (long)(*(int *)(orig_insn + 1)) + 5, 5); continue; } if (ud.mnemonic == UD_Ijmp && ud_insn_len(&ud) == 5) { x86_insert_jmp(insn, insn, se->pcall + 7); break; } } se->pcall_map = map_writable(se->pcall, 64); }
ã芧ã®ãšããããã®é¢æ°ã®äž»ãªåœ¹å²ã¯ããã³ãã©ãŒã®ã³ããŒãäœæãããã³ãã©ãŒãçŸåšã®ã¢ãã¬ã¹ã«æ§æããããšã§ãã ããã§ã¯éã¢ã»ã³ãã©ãç©æ¥µçã«äœ¿çšãããŠããŸãã ãã³ãã©ãŒã®åçŽãªæ§é ã«ãããè€éãªããžãã¯ãªãã§å®è¡ã§ããŸãã ã«ãŒããçµäºããä¿¡å·ã¯ããã£ã¹ãããã£ã«å¶åŸ¡ãè¿ã
JMP REL32
æ€åºã§ãã
æºå段éã®åŸ
ã«ãã³ãŒããã«ãŒãã«ã³ãŒãã«
åã蟌ã段éãç¶ããŸãã ãã®ãã§ãŒãºã¯éåžžã«åçŽã§ãåã·ã¹ãã ãµãŒãã¹ã®ã³ãŒãã«åäžã®åœä»€ïŒ
JMP REL32
ïŒãèšè¿°ããããšã§æ§æãããŸãã
ã¢ãžã¥ãŒã«ãã¢ã³ããŒãããããšã
埩å
ãã§ãŒãºãæåã«å®è¡ãããŸããããã¯ãã·ã¹ãã ã³ãŒã«ãã£ã¹ãããã£ãŒã®ã³ãŒãã®åŸ©å
ãšããã³ãã©ãŒã®ã³ãŒãã®å€æŽã§æ§æãããŸãã
static void generic_restore(scentry_t *se) { ud_t ud; if (!se->pcall_map) return; ud_initialize(&ud, BITS_PER_LONG, \ UD_VENDOR_ANY, se->stub, STUB_SIZE); while (ud_disassemble(&ud)) { if (ud.mnemonic == UD_Icall && ud_insn_len(&ud) == 5) { memset(se->stub + ud_insn_off(&ud), 0x90, ud_insn_len(&ud)); continue; } if (ud.mnemonic == UD_Ijmp) break; } debug(" [o] restoring original call instruction %p (%s)\n", se->pcall, se->name); x86_insert_call(se->pcall_map, NULL, se->table, 7); }
ã芧ã®ãšããããã³ãã©ã³ãŒãã§ã¯ãèŠã€ãã£ã5ãã€ãã®CALLã³ãã³ãã¯ãã¹ãŠNOPã®ã·ãŒã±ã³ã¹ã«çœ®ãæããããã·ã¹ãã ã³ãŒã«ããæ»ã£ããšãã«ååšããªãã³ãŒããå®è¡ããããšããè©Šã¿ãé€å€ããŸãã ããã«ã€ããŠã¯åã«èª¬æããŸããã
泚å
¥ããã³åŸ©å
ãã§ãŒãºã«å¯Ÿå¿ããæ©èœã¯
stop_machine
ã®ã³ã³ããã¹ãã§å®è¡ãããããã䜿çšãããã¹ãŠã®ãããã³ã°ãäºåã«æºåããå¿
èŠããããŸãã
ã¢ã³ããŒãäžã®æåŸã®ãã§ãŒãºã¯
clenupãã§ãŒãºã§ãå
éšãªãœãŒã¹ïŒ
pcall_map
ïŒã
pcall_map
ãŸãã
ã¢ãžã¥ãŒã«ãã¢ã³ããŒããããåŸããã³ãã©ãŒã®ã³ãŒããå«ãé å
ã¯åžžã«ã«ãŒãã«ã¡ã¢ãªã«æ®ãããšã«æ³šæããŠãã ããã åè¿°ã®ããã«ãããã¯ã¢ãžã¥ãŒã«ãã¢ã³ããŒãããåŸã«ã·ã¹ãã ãæ£ããåäœãããããã®åææ¡ä»¶ã§ãã
ãããã£ãŠãã«ãŒãã«ã·ã¹ãã ã³ãŒã«ãã·ã¹ãã ã³ãŒã«ã®ã¡ã«ããºã ã«åã蟌ãåºæ¬ååãäŸã䜿çšããŠåæããããããã€ã³ã¿ãŒã»ããããå¯èœæ§ã瀺ããŸãã
VIã ãã¹ããšãããã°
ãã¹ãã®ããã«ã
open(2)
ã·ã¹ãã ã³ãŒã«ãã€ã³ã¿ãŒã»ããããŸãã 以äžã¯ã
ServiceTraceEnterãã³ãã©ãŒã䜿çšããŠãã®ã€ã³ã¿ãŒã»ãããå®è£
ãã
trace_syscall_entryé¢æ°ã§ãã
static void trace_syscall_entry(int arch, unsigned long major, \ unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3) { char *filename = NULL; if (major == __NR_open || major == __NR_ia32_open) { filename = kmalloc(PATH_MAX, GFP_KERNEL); if (!filename || strncpy_from_user(filename, (const void __user *)a0, PATH_MAX) < 0) goto out; printk("%s open(%s) [%s]\n", arch ? "X86_64" : "I386", filename, current->comm); } out: if (filename) kfree(filename); } void ServiceTraceEnter(struct pt_regs *regs) { if (IS_IA32) trace_syscall_entry(0, regs->orig_ax, \ regs->bx, regs->cx, regs->dx, regs->si); #ifdef CONFIG_X86_64 else trace_syscall_entry(1, regs->orig_ax, \ regs->di, regs->si, regs->dx, regs->r10); #endif }
ã¢ãžã¥ãŒã«ã®çµã¿ç«ãŠãšããŒãã¯ãæšæºçãªæ¹æ³ã§å®è¡ãããŸãã
$ git clone https://github.com/milabs/kmod_hooking_sct $ cd kmod_hooking_sct $ make $ sudo insmod scthook.ko
ãã®çµæã次ã®æ
å ±ãã«ãŒãã«ãã°ã«è¡šç€ºãããã¯ãã§ãïŒ
dmesg
ïŒïŒ
[ 5217.779766] [scthook]
open(2)
ã€ã³ã¿ãŒã»ãããæ£ããéçºãããšãåããã°ã«æ¬¡ã®ãããªã¡ãã»ãŒãžã衚瀺ãããŸãã
[ 5370.999929] X86_64 open(/usr/share/locale-langpack/en_US.utf8/LC_MESSAGES/libc.mo) [perl] [ 5370.999930] X86_64 open(/usr/share/locale-langpack/en_US/LC_MESSAGES/libc.mo) [perl] [ 5370.999932] X86_64 open(/usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/libc.mo) [perl] [ 5370.999934] X86_64 open(/usr/share/locale-langpack/en.utf8/LC_MESSAGES/libc.mo) [perl] [ 5370.999936] X86_64 open(/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo) [perl] [ 5371.001308] X86_64 open(/etc/login.defs) [cron] [ 5372.422399] X86_64 open(/home/ilya/.cache/awesome/history) [awesome] [ 5372.424013] X86_64 open(/dev/null) [awesome] [ 5372.424682] I386 open(/etc/ld.so.cache) [skype] [ 5372.424714] I386 open(/usr/lib/i386-linux-gnu/libXv.so.1) [skype] [ 5372.424753] I386 open(/usr/lib/i386-linux-gnu/libXss.so.1) [skype] [ 5372.424789] I386 open(/lib/i386-linux-gnu/librt.so.1) [skype] [ 5372.424827] I386 open(/lib/i386-linux-gnu/libdl.so.2) [skype] [ 5372.424856] I386 open(/usr/lib/i386-linux-gnu/libX11.so.6) [skype] [ 5372.424896] I386 open(/usr/lib/i386-linux-gnu/libXext.so.6) [skype] [ 5372.424929] I386 open(/usr/lib/i386-linux-gnu/libQtDBus.so.4) [skype] [ 5372.424961] I386 open(/usr/lib/i386-linux-gnu/libQtWebKit.so.4) [skype] [ 5372.425003] I386 open(/usr/lib/i386-linux-gnu/libQtXml.so.4) [skype] [ 5372.425035] I386 open(/usr/lib/i386-linux-gnu/libQtGui.so.4) [skype] [ 5372.425072] I386 open(/usr/lib/i386-linux-gnu/libQtNetwork.so.4) [skype] [ 5372.425103] I386 open(/usr/lib/i386-linux-gnu/libQtCore.so.4) [skype] [ 5372.425151] I386 open(/lib/i386-linux-gnu/libpthread.so.0) [skype] [ 5372.425191] I386 open(/usr/lib/i386-linux-gnu/libstdc++.so.6) [skype] [ 5372.425233] I386 open(/lib/i386-linux-gnu/libm.so.6) [skype] [ 5372.425265] I386 open(/lib/i386-linux-gnu/libgcc_s.so.1) [skype] [ 5372.425292] I386 open(/lib/i386-linux-gnu/libc.so.6) [skype] [ 5372.425338] I386 open(/usr/lib/i386-linux-gnu/libxcb.so.1) [skype] [ 5372.425380] I386 open(/lib/i386-linux-gnu/libdbus-1.so.3) [skype] [ 5372.425416] I386 open(/lib/i386-linux-gnu/libz.so.1) [skype] [ 5372.425444] I386 open(/usr/lib/i386-linux-gnu/libXrender.so.1) [skype] [ 5372.425475] I386 open(/usr/lib/i386-linux-gnu/libjpeg.so.8) [skype] [ 5372.425510] I386 open(/lib/i386-linux-gnu/libpng12.so.0) [skype] [ 5372.425546] I386 open(/usr/lib/i386-linux-gnu/libxslt.so.1) [skype] [ 5372.425579] I386 open(/usr/lib/i386-linux-gnu/libxml2.so.2) [skype]
, 32- (, Skype) , , I386, X86_64. ,
open(2)
.
VII. ãããã«
Linux , . , , , . .
, ,
github .