Advertisement
Spider64

2.6.32 2013 local Exploit 2013

Sep 19th, 2013
504
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.21 KB | None | 0 0
  1. ===============================================
  2. Linux Kernel 2.6.32 Local Root Exploit (x86_64)
  3. | canomer | ~ | SiberAjan|
  4. ===============================================
  5.  
  6.  
  7.  
  8. #define _GNU_SOURCE
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #define KSYM_NAME_LEN 127
  16.  
  17.  
  18. struct sym_entry {
  19. unsigned long long addr;
  20. unsigned int len;
  21. unsigned char *sym;
  22. };
  23.  
  24.  
  25. static struct sym_entry *table;
  26. static unsigned int table_size, table_cnt;
  27. static unsigned long long _text, _stext, _etext, _sinittext, _einittext, _***tratext, _eextratext;
  28. static int all_symbols = 0;
  29. static char symbol_prefix_char = '\0';
  30.  
  31. int token_profit[0x10000];
  32.  
  33. /* the table that holds the result of the compression */
  34. unsigned char best_table[256][2];
  35. unsigned char best_table_len[256];
  36.  
  37.  
  38. static void usage(void)
  39. {
  40. fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n");
  41. exit(1);
  42. }
  43.  
  44. /*
  45. * This ignores the intensely annoying "mapping symbols" found
  46. * in ARM ELF files: $a, $t and $d.
  47. */
  48. static inline int is_arm_mapping_symbol(const char *str)
  49. {
  50. return str[0] == '$' && strchr("atd", str[1])
  51. && (str[2] == '\0' || str[2] == '.');
  52. }
  53.  
  54. static int read_symbol(FILE *in, struct sym_entry *s)
  55. {
  56. char str[500];
  57. char *sym, stype;
  58. int rc;
  59.  
  60. rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
  61. if (rc != 3) {
  62. if (rc != EOF) {
  63. /* skip line */
  64. fgets(str, 500, in);
  65. }
  66. return -1;
  67. }
  68.  
  69. sym = str;
  70. /* skip prefix char */
  71. if (symbol_prefix_char && str[0] == symbol_prefix_char)
  72. sym++;
  73.  
  74. /* Ignore most absolute/undefined (?) symbols. */
  75. if (strcmp(sym, "_text") == 0)
  76. _text = s->addr;
  77. else if (strcmp(sym, "_stext") == 0)
  78. _stext = s->addr;
  79. else if (strcmp(sym, "_etext") == 0)
  80. _etext = s->addr;
  81. else if (strcmp(sym, "_sinittext") == 0)
  82. _sinittext = s->addr;
  83. else if (strcmp(sym, "_einittext") == 0)
  84. _einittext = s->addr;
  85. else if (strcmp(sym, "_***tratext") == 0)
  86. _***tratext = s->addr;
  87. else if (strcmp(sym, "_eextratext") == 0)
  88. _eextratext = s->addr;
  89. else if (toupper(stype) == 'A')
  90. {
  91. /* Keep these useful absolute symbols */
  92. if (strcmp(sym, "__kernel_syscall_via_break") &&
  93. strcmp(sym, "__kernel_syscall_via_epc") &&
  94. strcmp(sym, "__kernel_sigtramp") &&
  95. strcmp(sym, "__gp"))
  96. return -1;
  97.  
  98. }
  99. else if (toupper(stype) == 'U' ||
  100. is_arm_mapping_symbol(sym))
  101. return -1;
  102. /* exclude also MIPS ELF local symbols ($L123 instead of .L123) */
  103. else if (str[0] == '$')
  104. return -1;
  105.  
  106. /* include the type field in the symbol name, so that it gets
  107. * compressed together */
  108. s->len = strlen(str) + 1;
  109. s->sym = malloc(s->len + 1);
  110. if (!s->sym) {
  111. fprintf(stderr, "kallsyms failure: "
  112. "unable to allocate required amount of memory\n");
  113. exit(EXIT_FAILURE);
  114. }
  115. strcpy((char *)s->sym + 1, str);
  116. s->sym[0] = stype;
  117.  
  118. return 0;
  119. }
  120.  
  121. static int symbol_valid(struct sym_entry *s)
  122. {
  123. /* Symbols which vary between passes. Passes 1 and 2 must have
  124. * identical symbol lists. The kallsyms_* symbols below are only added
  125. * after pass 1, they would be included in pass 2 when --all-symbols is
  126. * specified so exclude them to get a stable symbol list.
  127. */
  128. static char *special_symbols[] = {
  129. "kallsyms_addresses",
  130. "kallsyms_num_syms",
  131. "kallsyms_names",
  132. "kallsyms_markers",
  133. "kallsyms_token_table",
  134. "kallsyms_token_index",
  135.  
  136. /* Exclude linker generated symbols which vary between passes */
  137. "_SDA_BASE_", /* ppc */
  138. "_SDA2_BASE_", /* ppc */
  139. NULL };
  140. int i;
  141. int offset = 1;
  142.  
  143. /* skip prefix char */
  144. if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char)
  145. offset++;
  146.  
  147. /* if --all-symbols is not specified, then symbols outside the text
  148. * and inittext sections are discarded */
  149. if (!all_symbols) {
  150. if ((s->addr < _stext || s->addr > _etext)
  151. && (s->addr < _sinittext || s->addr > _einittext)
  152. && (s->addr < _***tratext || s->addr > _eextratext))
  153. return 0;
  154. /* Corner case. Discard any symbols with the same value as
  155. * _etext _einittext or _eextratext; they can move between pass
  156. * 1 and 2 when the kallsyms data are added. If these symbols
  157. * move then they may get dropped in pass 2, which breaks the
  158. * kallsyms rules.
  159. */
  160. if ((s->addr == _etext && strcmp((char*)s->sym + offset, "_etext")) ||
  161. (s->addr == _einittext && strcmp((char*)s->sym + offset, "_einittext")) ||
  162. (s->addr == _eextratext && strcmp((char*)s->sym + offset, "_eextratext")))
  163. return 0;
  164. }
  165.  
  166. /* Exclude symbols which vary between passes. */
  167. if (strstr((char *)s->sym + offset, "_compiled."))
  168. return 0;
  169.  
  170. for (i = 0; special_symbols[i]; i++)
  171. if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 )
  172. return 0;
  173.  
  174. return 1;
  175. }
  176.  
  177. static void read_map(FILE *in)
  178. {
  179. while (!feof(in)) {
  180. if (table_cnt >= table_size) {
  181. table_size += 10000;
  182. table = realloc(table, sizeof(*table) * table_size);
  183. if (!table) {
  184. fprintf(stderr, "out of memory\n");
  185. exit (1);
  186. }
  187. }
  188. if (read_symbol(in, &table[table_cnt]) == 0)
  189. table_cnt++;
  190. }
  191. }
  192.  
  193. static void output_label(char *label)
  194. {
  195. if (symbol_prefix_char)
  196. printf(".globl %c%s\n", symbol_prefix_char, label);
  197. else
  198. printf(".globl %s\n", label);
  199. printf("\tALGN\n");
  200. if (symbol_prefix_char)
  201. printf("%c%s:\n", symbol_prefix_char, label);
  202. else
  203. printf("%s:\n", label);
  204. }
  205.  
  206. /* uncompress a compressed symbol. When this function is called, the best table
  207. * might still be compressed itself, so the function needs to be recursive */
  208. static int expand_symbol(unsigned char *data, int len, char *result)
  209. {
  210. int c, rlen, total=0;
  211.  
  212. while (len) {
  213. c = *data;
  214. /* if the table holds a single char that is the same as the one
  215. * we are looking for, then end the search */
  216. if (best_table[c][0]==c && best_table_len[c]==1) {
  217. *result++ = c;
  218. total++;
  219. } else {
  220. /* if not, recurse and expand */
  221. rlen = expand_symbol(best_table[c], best_table_len[c], result);
  222. total += rlen;
  223. result += rlen;
  224. }
  225. data++;
  226. len--;
  227. }
  228. *result=0;
  229.  
  230. return total;
  231. }
  232.  
  233. static void write_src(void)
  234. {
  235. unsigned int i, k, off;
  236. unsigned int best_idx[256];
  237. unsigned int *markers;
  238. char buf[KSYM_NAME_LEN+1];
  239.  
  240. printf("#include <asm/types.h>\n");
  241. printf("#if BITS_PER_LONG == 64\n");
  242. printf("#define PTR .quad\n");
  243. printf("#define ALGN .align 8\n");
  244. printf("#else\n");
  245. printf("#define PTR .long\n");
  246. printf("#define ALGN .align 4\n");
  247. printf("#endif\n");
  248.  
  249. printf(".data\n");
  250.  
  251. /* Provide proper symbols relocatability by their '_text'
  252. * relativeness. The symbol names cannot be used to construct
  253. * normal symbol references as the list of symbols contains
  254. * symbols that are declared static and are private to their
  255. * .o files. This prevents .tmp_kallsyms.o or any other
  256. * object from referencing them.
  257. */
  258. output_label("kallsyms_addresses");
  259. for (i = 0; i < table_cnt; i++) {
  260. if (toupper(table[i].sym[0]) != 'A') {
  261. printf("\tPTR\t_text + %#llx\n",
  262. table[i].addr - _text);
  263. } else {
  264. printf("\tPTR\t%#llx\n", table[i].addr);
  265. }
  266. }
  267. printf("\n");
  268.  
  269. output_label("kallsyms_num_syms");
  270. printf("\tPTR\t%d\n", table_cnt);
  271. printf("\n");
  272.  
  273. /* table of offset markers, that give the offset in the compressed stream
  274. * every 256 symbols */
  275. markers = malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
  276. if (!markers) {
  277. fprintf(stderr, "kallsyms failure: "
  278. "unable to allocate required memory\n");
  279. exit(EXIT_FAILURE);
  280. }
  281.  
  282. output_label("kallsyms_names");
  283. off = 0;
  284. for (i = 0; i < table_cnt; i++) {
  285. if ((i & 0xFF) == 0)
  286. markers[i >> 8] = off;
  287.  
  288. printf("\t.byte 0x%02x", table[i].len);
  289. for (k = 0; k < table[i].len; k++)
  290. printf(", 0x%02x", table[i].sym[k]);
  291. printf("\n");
  292.  
  293. off += table[i].len + 1;
  294. }
  295. printf("\n");
  296.  
  297. output_label("kallsyms_markers");
  298. for (i = 0; i < ((table_cnt + 255) >> 8); i++)
  299. printf("\tPTR\t%d\n", markers[i]);
  300. printf("\n");
  301.  
  302. free(markers);
  303.  
  304. output_label("kallsyms_token_table");
  305. off = 0;
  306. for (i = 0; i < 256; i++) {
  307. best_idx[i] = off;
  308. expand_symbol(best_table[i], best_table_len[i], buf);
  309. printf("\t.asciz\t\"%s\"\n", buf);
  310. off += strlen(buf) + 1;
  311. }
  312. printf("\n");
  313.  
  314. output_label("kallsyms_token_index");
  315. for (i = 0; i < 256; i++)
  316. printf("\t.short\t%d\n", best_idx[i]);
  317. printf("\n");
  318. }
  319.  
  320.  
  321. /* table lookup compression functions */
  322.  
  323. /* count all the possible tokens in a symbol */
  324. static void learn_symbol(unsigned char *symbol, int len)
  325. {
  326. int i;
  327.  
  328. for (i = 0; i < len - 1; i++)
  329. token_profit[ symbol[i] + (symbol[i + 1] << 8) ]++;
  330. }
  331.  
  332. /* decrease the count for all the possible tokens in a symbol */
  333. static void forget_symbol(unsigned char *symbol, int len)
  334. {
  335. int i;
  336.  
  337. for (i = 0; i < len - 1; i++)
  338. token_profit[ symbol[i] + (symbol[i + 1] << 8) ]--;
  339. }
  340.  
  341. /* remove all the invalid symbols from the table and do the initial token count */
  342. static void build_initial_tok_table(void)
  343. {
  344. unsigned int i, pos;
  345.  
  346. pos = 0;
  347. for (i = 0; i < table_cnt; i++) {
  348. if ( symbol_valid(&table[i]) ) {
  349. if (pos != i)
  350. table[pos] = table[i];
  351. learn_symbol(table[pos].sym, table[pos].len);
  352. pos++;
  353. }
  354. }
  355. table_cnt = pos;
  356. }
  357.  
  358. /* replace a given token in all the valid symbols. Use the sampled symbols
  359. * to update the counts */
  360. static void compress_symbols(unsigned char *str, int idx)
  361. {
  362. unsigned int i, len, size;
  363. unsigned char *p1, *p2;
  364.  
  365. for (i = 0; i < table_cnt; i++) {
  366.  
  367. len = table[i].len;
  368. p1 = table[i].sym;
  369.  
  370. /* find the token on the symbol */
  371. p2 = memmem(p1, len, str, 2);
  372. if (!p2) continue;
  373.  
  374. /* decrease the counts for this symbol's tokens */
  375. forget_symbol(table[i].sym, len);
  376. size = len;
  377. do {
  378. *p2 = idx;
  379. p2++;
  380. size -= (p2 - p1);
  381. memmove(p2, p2 + 1, size);
  382. p1 = p2;
  383. len--;
  384. if (size < 2) break;
  385. /* find the token on the symbol */
  386. p2 = memmem(p1, size, str, 2);
  387. } while (p2);
  388. table[i].len = len;
  389. /* increase the counts for this symbol's new tokens */
  390. learn_symbol(table[i].sym, len);
  391. }
  392. }
  393.  
  394. /* search the token with the maximum profit */
  395. static int find_best_token(void)
  396. {
  397. int i, best, bestprofit;
  398.  
  399. bestprofit=-10000;
  400. best = 0;
  401.  
  402. for (i = 0; i < 0x10000; i++) {
  403. if (token_profit[i] > bestprofit) {
  404. best = i;
  405. bestprofit = token_profit[i];
  406. }
  407. }
  408. return best;
  409. }
  410.  
  411. /* this is the core of the algorithm: calculate the "best" table */
  412. static void optimize_result(void)
  413. {
  414. int i, best;
  415.  
  416. /* using the '\0' symbol last allows compress_symbols to use standard
  417. * fast string functions */
  418. for (i = 255; i >= 0; i--) {
  419.  
  420. /* if this table slot is empty (it is not used by an actual
  421. * original char code */
  422. if (!best_table_len[i]) {
  423.  
  424. /* find the token with the breates profit value */
  425. best = find_best_token();
  426.  
  427. /* place it in the "best" table */
  428. best_table_len[i] = 2;
  429. best_table[i][0] = best & 0xFF;
  430. best_table[i][1] = (best >> 8) & 0xFF;
  431.  
  432. /* replace this token in all the valid symbols */
  433. compress_symbols(best_table[i], i);
  434. }
  435. }
  436. }
  437.  
  438. /* start by placing the symbols that are actually used on the table */
  439. static void insert_real_symbols_in_table(void)
  440. {
  441. unsigned int i, j, c;
  442.  
  443. memset(best_table, 0, sizeof(best_table));
  444. memset(best_table_len, 0, sizeof(best_table_len));
  445.  
  446. for (i = 0; i < table_cnt; i++) {
  447. for (j = 0; j < table[i].len; j++) {
  448. c = table[i].sym[j];
  449. best_table[c][0]=c;
  450. best_table_len[c]=1;
  451. }
  452. }
  453. }
  454.  
  455. static void optimize_token_table(void)
  456. {
  457. build_initial_tok_table();
  458.  
  459. insert_real_symbols_in_table();
  460.  
  461. /* When valid symbol is not registered, exit to error */
  462. if (!table_cnt) {
  463. fprintf(stderr, "No valid symbol.\n");
  464. exit(1);
  465. }
  466.  
  467. optimize_result();
  468. }
  469.  
  470.  
  471. int main(int argc, char **argv)
  472. {
  473. if (argc >= 2) {
  474. int i;
  475. for (i = 1; i < argc; i++) {
  476. if(strcmp(argv[i], "--all-symbols") == 0)
  477. all_symbols = 1;
  478. else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) {
  479. char *p = &argv[i][16];
  480. /* skip quote */
  481. if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\''))
  482. p++;
  483. symbol_prefix_char = *p;
  484. } else
  485. usage();
  486. }
  487. } else if (argc != 1)
  488. usage();
  489.  
  490. read_map(stdin);
  491. optimize_token_table();
  492. write_src();
  493.  
  494. return 0;
  495. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement