Advertisement
Guest User

2.6.32 [x86_64] Local Root Exploit

a guest
Jan 2nd, 2016
494
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.81 KB | None | 0 0
  1. Author = bRpsd
  2.  
  3. Titile = Linux Kernel 2.6.32 Local Root Exploit (x86_64)
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15. #define _GNU_SOURCE
  16.  
  17.  
  18.  
  19. #include <stdio.h>
  20.  
  21. #include <stdlib.h>
  22.  
  23. #include <string.h>
  24.  
  25. #include <ctype.h>
  26.  
  27.  
  28.  
  29. #define KSYM_NAME_LEN 127
  30.  
  31.  
  32.  
  33.  
  34.  
  35. struct sym_entry {
  36.  
  37. unsigned long long addr;
  38.  
  39. unsigned int len;
  40.  
  41. unsigned char *sym;
  42.  
  43. };
  44.  
  45.  
  46.  
  47.  
  48.  
  49. static struct sym_entry *table;
  50.  
  51. static unsigned int table_size, table_cnt;
  52.  
  53. static unsigned long long _text, _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
  54.  
  55. static int all_symbols = 0;
  56.  
  57. static char symbol_prefix_char = '\0';
  58.  
  59.  
  60.  
  61. int token_profit[0x10000];
  62.  
  63.  
  64.  
  65. /* the table that holds the result of the compression */
  66.  
  67. unsigned char best_table[256][2];
  68.  
  69. unsigned char best_table_len[256];
  70.  
  71.  
  72.  
  73.  
  74.  
  75. static void usage(void)
  76.  
  77. {
  78.  
  79. fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n");
  80.  
  81. exit(1);
  82.  
  83. }
  84.  
  85.  
  86.  
  87. /*
  88.  
  89. * This ignores the intensely annoying "mapping symbols" found
  90.  
  91. * in ARM ELF files: $a, $t and $d.
  92.  
  93. */
  94.  
  95. static inline int is_arm_mapping_symbol(const char *str)
  96.  
  97. {
  98.  
  99. return str[0] == '$' && strchr("atd", str[1])
  100.  
  101. && (str[2] == '\0' || str[2] == '.');
  102.  
  103. }
  104.  
  105.  
  106.  
  107. static int read_symbol(FILE *in, struct sym_entry *s)
  108.  
  109. {
  110.  
  111. char str[500];
  112.  
  113. char *sym, stype;
  114.  
  115. int rc;
  116.  
  117.  
  118.  
  119. rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
  120.  
  121. if (rc != 3) {
  122.  
  123. if (rc != EOF) {
  124.  
  125. /* skip line */
  126.  
  127. fgets(str, 500, in);
  128.  
  129. }
  130.  
  131. return -1;
  132.  
  133. }
  134.  
  135.  
  136.  
  137. sym = str;
  138.  
  139. /* skip prefix char */
  140.  
  141. if (symbol_prefix_char && str[0] == symbol_prefix_char)
  142.  
  143. sym++;
  144.  
  145.  
  146.  
  147. /* Ignore most absolute/undefined (?) symbols. */
  148.  
  149. if (strcmp(sym, "_text") == 0)
  150.  
  151. _text = s->addr;
  152.  
  153. else if (strcmp(sym, "_stext") == 0)
  154.  
  155. _stext = s->addr;
  156.  
  157. else if (strcmp(sym, "_etext") == 0)
  158.  
  159. _etext = s->addr;
  160.  
  161. else if (strcmp(sym, "_sinittext") == 0)
  162.  
  163. _sinittext = s->addr;
  164.  
  165. else if (strcmp(sym, "_einittext") == 0)
  166.  
  167. _einittext = s->addr;
  168.  
  169. else if (strcmp(sym, "_sextratext") == 0)
  170.  
  171. _sextratext = s->addr;
  172.  
  173. else if (strcmp(sym, "_eextratext") == 0)
  174.  
  175. _eextratext = s->addr;
  176.  
  177. else if (toupper(stype) == 'A')
  178.  
  179. {
  180.  
  181. /* Keep these useful absolute symbols */
  182.  
  183. if (strcmp(sym, "__kernel_syscall_via_break") &&
  184.  
  185. strcmp(sym, "__kernel_syscall_via_epc") &&
  186.  
  187. strcmp(sym, "__kernel_sigtramp") &&
  188.  
  189. strcmp(sym, "__gp"))
  190.  
  191. return -1;
  192.  
  193.  
  194.  
  195. }
  196.  
  197. else if (toupper(stype) == 'U' ||
  198.  
  199. is_arm_mapping_symbol(sym))
  200.  
  201. return -1;
  202.  
  203. /* exclude also MIPS ELF local symbols ($L123 instead of .L123) */
  204.  
  205. else if (str[0] == '$')
  206.  
  207. return -1;
  208.  
  209.  
  210.  
  211. /* include the type field in the symbol name, so that it gets
  212.  
  213. * compressed together */
  214.  
  215. s->len = strlen(str) + 1;
  216.  
  217. s->sym = malloc(s->len + 1);
  218.  
  219. if (!s->sym) {
  220.  
  221. fprintf(stderr, "kallsyms failure: "
  222.  
  223. "unable to allocate required amount of memory\n");
  224.  
  225. exit(EXIT_FAILURE);
  226.  
  227. }
  228.  
  229. strcpy((char *)s->sym + 1, str);
  230.  
  231. s->sym[0] = stype;
  232.  
  233.  
  234.  
  235. return 0;
  236.  
  237. }
  238.  
  239.  
  240.  
  241. static int symbol_valid(struct sym_entry *s)
  242.  
  243. {
  244.  
  245. /* Symbols which vary between passes. Passes 1 and 2 must have
  246.  
  247. * identical symbol lists. The kallsyms_* symbols below are only added
  248.  
  249. * after pass 1, they would be included in pass 2 when --all-symbols is
  250.  
  251. * specified so exclude them to get a stable symbol list.
  252.  
  253. */
  254.  
  255. static char *special_symbols[] = {
  256.  
  257. "kallsyms_addresses",
  258.  
  259. "kallsyms_num_syms",
  260.  
  261. "kallsyms_names",
  262.  
  263. "kallsyms_markers",
  264.  
  265. "kallsyms_token_table",
  266.  
  267. "kallsyms_token_index",
  268.  
  269.  
  270.  
  271. /* Exclude linker generated symbols which vary between passes */
  272.  
  273. "_SDA_BASE_", /* ppc */
  274.  
  275. "_SDA2_BASE_", /* ppc */
  276.  
  277. NULL };
  278.  
  279. int i;
  280.  
  281. int offset = 1;
  282.  
  283.  
  284.  
  285. /* skip prefix char */
  286.  
  287. if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char)
  288.  
  289. offset++;
  290.  
  291.  
  292.  
  293. /* if --all-symbols is not specified, then symbols outside the text
  294.  
  295. * and inittext sections are discarded */
  296.  
  297. if (!all_symbols) {
  298.  
  299. if ((s->addr < _stext || s->addr > _etext)
  300.  
  301. && (s->addr < _sinittext || s->addr > _einittext)
  302.  
  303. && (s->addr < _sextratext || s->addr > _eextratext))
  304.  
  305. return 0;
  306.  
  307. /* Corner case. Discard any symbols with the same value as
  308.  
  309. * _etext _einittext or _eextratext; they can move between pass
  310.  
  311. * 1 and 2 when the kallsyms data are added. If these symbols
  312.  
  313. * move then they may get dropped in pass 2, which breaks the
  314.  
  315. * kallsyms rules.
  316.  
  317. */
  318.  
  319. if ((s->addr == _etext && strcmp((char*)s->sym + offset, "_etext")) ||
  320.  
  321. (s->addr == _einittext && strcmp((char*)s->sym + offset, "_einittext")) ||
  322.  
  323. (s->addr == _eextratext && strcmp((char*)s->sym + offset, "_eextratext")))
  324.  
  325. return 0;
  326.  
  327. }
  328.  
  329.  
  330.  
  331. /* Exclude symbols which vary between passes. */
  332.  
  333. if (strstr((char *)s->sym + offset, "_compiled."))
  334.  
  335. return 0;
  336.  
  337.  
  338.  
  339. for (i = 0; special_symbols[i]; i++)
  340.  
  341. if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 )
  342.  
  343. return 0;
  344.  
  345.  
  346.  
  347. return 1;
  348.  
  349. }
  350.  
  351.  
  352.  
  353. static void read_map(FILE *in)
  354.  
  355. {
  356.  
  357. while (!feof(in)) {
  358.  
  359. if (table_cnt >= table_size) {
  360.  
  361. table_size += 10000;
  362.  
  363. table = realloc(table, sizeof(*table) * table_size);
  364.  
  365. if (!table) {
  366.  
  367. fprintf(stderr, "out of memory\n");
  368.  
  369. exit (1);
  370.  
  371. }
  372.  
  373. }
  374.  
  375. if (read_symbol(in, &table[table_cnt]) == 0)
  376.  
  377. table_cnt++;
  378.  
  379. }
  380.  
  381. }
  382.  
  383.  
  384.  
  385. static void output_label(char *label)
  386.  
  387. {
  388.  
  389. if (symbol_prefix_char)
  390.  
  391. printf(".globl %c%s\n", symbol_prefix_char, label);
  392.  
  393. else
  394.  
  395. printf(".globl %s\n", label);
  396.  
  397. printf("\tALGN\n");
  398.  
  399. if (symbol_prefix_char)
  400.  
  401. printf("%c%s:\n", symbol_prefix_char, label);
  402.  
  403. else
  404.  
  405. printf("%s:\n", label);
  406.  
  407. }
  408.  
  409.  
  410.  
  411. /* uncompress a compressed symbol. When this function is called, the best table
  412.  
  413. * might still be compressed itself, so the function needs to be recursive */
  414.  
  415. static int expand_symbol(unsigned char *data, int len, char *result)
  416.  
  417. {
  418.  
  419. int c, rlen, total=0;
  420.  
  421.  
  422.  
  423. while (len) {
  424.  
  425. c = *data;
  426.  
  427. /* if the table holds a single char that is the same as the one
  428.  
  429. * we are looking for, then end the search */
  430.  
  431. if (best_table[c][0]==c && best_table_len[c]==1) {
  432.  
  433. *result++ = c;
  434.  
  435. total++;
  436.  
  437. } else {
  438.  
  439. /* if not, recurse and expand */
  440.  
  441. rlen = expand_symbol(best_table[c], best_table_len[c], result);
  442.  
  443. total += rlen;
  444.  
  445. result += rlen;
  446.  
  447. }
  448.  
  449. data++;
  450.  
  451. len--;
  452.  
  453. }
  454.  
  455. *result=0;
  456.  
  457.  
  458.  
  459. return total;
  460.  
  461. }
  462.  
  463.  
  464.  
  465. static void write_src(void)
  466.  
  467. {
  468.  
  469. unsigned int i, k, off;
  470.  
  471. unsigned int best_idx[256];
  472.  
  473. unsigned int *markers;
  474.  
  475. char buf[KSYM_NAME_LEN+1];
  476.  
  477.  
  478.  
  479. printf("#include <asm/types.h>\n");
  480.  
  481. printf("#if BITS_PER_LONG == 64\n");
  482.  
  483. printf("#define PTR .quad\n");
  484.  
  485. printf("#define ALGN .align 8\n");
  486.  
  487. printf("#else\n");
  488.  
  489. printf("#define PTR .long\n");
  490.  
  491. printf("#define ALGN .align 4\n");
  492.  
  493. printf("#endif\n");
  494.  
  495.  
  496.  
  497. printf(".data\n");
  498.  
  499.  
  500.  
  501. /* Provide proper symbols relocatability by their '_text'
  502.  
  503. * relativeness. The symbol names cannot be used to construct
  504.  
  505. * normal symbol references as the list of symbols contains
  506.  
  507. * symbols that are declared static and are private to their
  508.  
  509. * .o files. This prevents .tmp_kallsyms.o or any other
  510.  
  511. * object from referencing them.
  512.  
  513. */
  514.  
  515. output_label("kallsyms_addresses");
  516.  
  517. for (i = 0; i < table_cnt; i++) {
  518.  
  519. if (toupper(table[i].sym[0]) != 'A') {
  520.  
  521. printf("\tPTR\t_text + %#llx\n",
  522.  
  523. table[i].addr - _text);
  524.  
  525. } else {
  526.  
  527. printf("\tPTR\t%#llx\n", table[i].addr);
  528.  
  529. }
  530.  
  531. }
  532.  
  533. printf("\n");
  534.  
  535.  
  536.  
  537. output_label("kallsyms_num_syms");
  538.  
  539. printf("\tPTR\t%d\n", table_cnt);
  540.  
  541. printf("\n");
  542.  
  543.  
  544.  
  545. /* table of offset markers, that give the offset in the compressed stream
  546.  
  547. * every 256 symbols */
  548.  
  549. markers = malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
  550.  
  551. if (!markers) {
  552.  
  553. fprintf(stderr, "kallsyms failure: "
  554.  
  555. "unable to allocate required memory\n");
  556.  
  557. exit(EXIT_FAILURE);
  558.  
  559. }
  560.  
  561.  
  562.  
  563. output_label("kallsyms_names");
  564.  
  565. off = 0;
  566.  
  567. for (i = 0; i < table_cnt; i++) {
  568.  
  569. if ((i & 0xFF) == 0)
  570.  
  571. markers[i >> 8] = off;
  572.  
  573.  
  574.  
  575. printf("\t.byte 0x%02x", table[i].len);
  576.  
  577. for (k = 0; k < table[i].len; k++)
  578.  
  579. printf(", 0x%02x", table[i].sym[k]);
  580.  
  581. printf("\n");
  582.  
  583.  
  584.  
  585. off += table[i].len + 1;
  586.  
  587. }
  588.  
  589. printf("\n");
  590.  
  591.  
  592.  
  593. output_label("kallsyms_markers");
  594.  
  595. for (i = 0; i < ((table_cnt + 255) >> 8); i++)
  596.  
  597. printf("\tPTR\t%d\n", markers[i]);
  598.  
  599. printf("\n");
  600.  
  601.  
  602.  
  603. free(markers);
  604.  
  605.  
  606.  
  607. output_label("kallsyms_token_table");
  608.  
  609. off = 0;
  610.  
  611. for (i = 0; i < 256; i++) {
  612.  
  613. best_idx[i] = off;
  614.  
  615. expand_symbol(best_table[i], best_table_len[i], buf);
  616.  
  617. printf("\t.asciz\t\"%s\"\n", buf);
  618.  
  619. off += strlen(buf) + 1;
  620.  
  621. }
  622.  
  623. printf("\n");
  624.  
  625.  
  626.  
  627. output_label("kallsyms_token_index");
  628.  
  629. for (i = 0; i < 256; i++)
  630.  
  631. printf("\t.short\t%d\n", best_idx[i]);
  632.  
  633. printf("\n");
  634.  
  635. }
  636.  
  637.  
  638.  
  639.  
  640.  
  641. /* table lookup compression functions */
  642.  
  643.  
  644.  
  645. /* count all the possible tokens in a symbol */
  646.  
  647. static void learn_symbol(unsigned char *symbol, int len)
  648.  
  649. {
  650.  
  651. int i;
  652.  
  653.  
  654.  
  655. for (i = 0; i < len - 1; i++)
  656.  
  657. token_profit[ symbol[i] + (symbol[i + 1] << 8) ]++;
  658.  
  659. }
  660.  
  661.  
  662.  
  663. /* decrease the count for all the possible tokens in a symbol */
  664.  
  665. static void forget_symbol(unsigned char *symbol, int len)
  666.  
  667. {
  668.  
  669. int i;
  670.  
  671.  
  672.  
  673. for (i = 0; i < len - 1; i++)
  674.  
  675. token_profit[ symbol[i] + (symbol[i + 1] << 8) ]--;
  676.  
  677. }
  678.  
  679.  
  680.  
  681. /* remove all the invalid symbols from the table and do the initial token count */
  682.  
  683. static void build_initial_tok_table(void)
  684.  
  685. {
  686.  
  687. unsigned int i, pos;
  688.  
  689.  
  690.  
  691. pos = 0;
  692.  
  693. for (i = 0; i < table_cnt; i++) {
  694.  
  695. if ( symbol_valid(&table[i]) ) {
  696.  
  697. if (pos != i)
  698.  
  699. table[pos] = table[i];
  700.  
  701. learn_symbol(table[pos].sym, table[pos].len);
  702.  
  703. pos++;
  704.  
  705. }
  706.  
  707. }
  708.  
  709. table_cnt = pos;
  710.  
  711. }
  712.  
  713.  
  714.  
  715. /* replace a given token in all the valid symbols. Use the sampled symbols
  716.  
  717. * to update the counts */
  718.  
  719. static void compress_symbols(unsigned char *str, int idx)
  720.  
  721. {
  722.  
  723. unsigned int i, len, size;
  724.  
  725. unsigned char *p1, *p2;
  726.  
  727.  
  728.  
  729. for (i = 0; i < table_cnt; i++) {
  730.  
  731.  
  732.  
  733. len = table[i].len;
  734.  
  735. p1 = table[i].sym;
  736.  
  737.  
  738.  
  739. /* find the token on the symbol */
  740.  
  741. p2 = memmem(p1, len, str, 2);
  742.  
  743. if (!p2) continue;
  744.  
  745.  
  746.  
  747. /* decrease the counts for this symbol's tokens */
  748.  
  749. forget_symbol(table[i].sym, len);
  750.  
  751.  
  752.  
  753. size = len;
  754.  
  755.  
  756.  
  757. do {
  758.  
  759. *p2 = idx;
  760.  
  761. p2++;
  762.  
  763. size -= (p2 - p1);
  764.  
  765. memmove(p2, p2 + 1, size);
  766.  
  767. p1 = p2;
  768.  
  769. len--;
  770.  
  771.  
  772.  
  773. if (size < 2) break;
  774.  
  775.  
  776.  
  777. /* find the token on the symbol */
  778.  
  779. p2 = memmem(p1, size, str, 2);
  780.  
  781.  
  782.  
  783. } while (p2);
  784.  
  785.  
  786.  
  787. table[i].len = len;
  788.  
  789.  
  790.  
  791. /* increase the counts for this symbol's new tokens */
  792.  
  793. learn_symbol(table[i].sym, len);
  794.  
  795. }
  796.  
  797. }
  798.  
  799.  
  800.  
  801. /* search the token with the maximum profit */
  802.  
  803. static int find_best_token(void)
  804.  
  805. {
  806.  
  807. int i, best, bestprofit;
  808.  
  809.  
  810.  
  811. bestprofit=-10000;
  812.  
  813. best = 0;
  814.  
  815.  
  816.  
  817. for (i = 0; i < 0x10000; i++) {
  818.  
  819. if (token_profit[i] > bestprofit) {
  820.  
  821. best = i;
  822.  
  823. bestprofit = token_profit[i];
  824.  
  825. }
  826.  
  827. }
  828.  
  829. return best;
  830.  
  831. }
  832.  
  833.  
  834.  
  835. /* this is the core of the algorithm: calculate the "best" table */
  836.  
  837. static void optimize_result(void)
  838.  
  839. {
  840.  
  841. int i, best;
  842.  
  843.  
  844.  
  845. /* using the '\0' symbol last allows compress_symbols to use standard
  846.  
  847. * fast string functions */
  848.  
  849. for (i = 255; i >= 0; i--) {
  850.  
  851.  
  852.  
  853. /* if this table slot is empty (it is not used by an actual
  854.  
  855. * original char code */
  856.  
  857. if (!best_table_len[i]) {
  858.  
  859.  
  860.  
  861. /* find the token with the breates profit value */
  862.  
  863. best = find_best_token();
  864.  
  865.  
  866.  
  867. /* place it in the "best" table */
  868.  
  869. best_table_len[i] = 2;
  870.  
  871. best_table[i][0] = best & 0xFF;
  872.  
  873. best_table[i][1] = (best >> 8) & 0xFF;
  874.  
  875.  
  876.  
  877. /* replace this token in all the valid symbols */
  878.  
  879. compress_symbols(best_table[i], i);
  880.  
  881. }
  882.  
  883. }
  884.  
  885. }
  886.  
  887.  
  888.  
  889. /* start by placing the symbols that are actually used on the table */
  890.  
  891. static void insert_real_symbols_in_table(void)
  892.  
  893. {
  894.  
  895. unsigned int i, j, c;
  896.  
  897.  
  898.  
  899. memset(best_table, 0, sizeof(best_table));
  900.  
  901. memset(best_table_len, 0, sizeof(best_table_len));
  902.  
  903.  
  904.  
  905. for (i = 0; i < table_cnt; i++) {
  906.  
  907. for (j = 0; j < table[i].len; j++) {
  908.  
  909. c = table[i].sym[j];
  910.  
  911. best_table[c][0]=c;
  912.  
  913. best_table_len[c]=1;
  914.  
  915. }
  916.  
  917. }
  918.  
  919. }
  920.  
  921.  
  922.  
  923. static void optimize_token_table(void)
  924.  
  925. {
  926.  
  927. build_initial_tok_table();
  928.  
  929.  
  930.  
  931. insert_real_symbols_in_table();
  932.  
  933.  
  934.  
  935. /* When valid symbol is not registered, exit to error */
  936.  
  937. if (!table_cnt) {
  938.  
  939. fprintf(stderr, "No valid symbol.\n");
  940.  
  941. exit(1);
  942.  
  943. }
  944.  
  945.  
  946.  
  947. optimize_result();
  948.  
  949. }
  950.  
  951.  
  952.  
  953.  
  954.  
  955. int main(int argc, char **argv)
  956.  
  957. {
  958.  
  959. if (argc >= 2) {
  960.  
  961. int i;
  962.  
  963. for (i = 1; i < argc; i++) {
  964.  
  965. if(strcmp(argv[i], "--all-symbols") == 0)
  966.  
  967. all_symbols = 1;
  968.  
  969. else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) {
  970.  
  971. char *p = &argv[i][16];
  972.  
  973. /* skip quote */
  974.  
  975. if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\''))
  976.  
  977. p++;
  978.  
  979. symbol_prefix_char = *p;
  980.  
  981. } else
  982.  
  983. usage();
  984.  
  985. }
  986.  
  987. } else if (argc != 1)
  988.  
  989. usage();
  990.  
  991.  
  992.  
  993. read_map(stdin);
  994.  
  995. optimize_token_table();
  996.  
  997. write_src();
  998.  
  999.  
  1000.  
  1001. return 0;
  1002.  
  1003. }
  1004.  
  1005. [2014-12-29]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement