Advertisement
Guest User

Untitled

a guest
Mar 19th, 2018
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.12 KB | None | 0 0
  1. #include <sys/types.h>
  2. #include <unistd.h>
  3.  
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <stdbool.h>
  8. #include <stdint.h>
  9. #include <stdlib.h>
  10.  
  11. #define BUFFER_SIZE 1024*4
  12.  
  13. int magic_function() {
  14. // Defined volatile to stop them from being optimized out.
  15. volatile uint64_t a = 0x0011223344556677;
  16. volatile uint64_t b = 0x8899aabbccddeeff;
  17. volatile uint64_t c = 0;
  18. volatile uint64_t d = 0;
  19. volatile char buffer[BUFFER_SIZE] = {0};
  20.  
  21. return a + b + c + d;
  22. }
  23.  
  24. __attribute__((__noreturn__))
  25. void fail(const char* msg) {
  26. printf("%s failed: %s\n", msg, strerror(errno));
  27.  
  28. exit(EXIT_FAILURE);
  29. }
  30.  
  31. uint64_t get_stack_base() {
  32. char buffer[4096];
  33. FILE* fp;
  34.  
  35. // Build command that returns the stack base of current process.
  36. sprintf(buffer, "cat /proc/%d/maps | grep stack | awk -F'-' '{print $1}'", getpid());
  37.  
  38. // Execute command.
  39. if(!(fp = popen(buffer, "r"))) {
  40. fail("popen");
  41. }
  42.  
  43. // Read command output.
  44. if(!fgets(buffer, 4096, fp)) {
  45. fail("fgets");
  46. }
  47.  
  48. pclose(fp);
  49.  
  50. // Parse output (hex address).
  51. errno = 0;
  52. uint64_t result = strtoull(buffer, NULL, 16);
  53. if(errno) {
  54. fail("strtoull");
  55. }
  56.  
  57. return result;
  58. }
  59.  
  60. void* checked_malloc(size_t size) {
  61. void* result = malloc(size);
  62.  
  63. if(!result) {
  64. fail("malloc");
  65. }
  66.  
  67. return result;
  68. }
  69.  
  70. int main(int argc, char** argv) {
  71. uint64_t rsp;
  72. uint64_t rbp;
  73.  
  74. // Grab content of rsp & rbp registers.
  75. __asm__ ("movq %%rsp, %0" : "=r" (rsp) );
  76. __asm__ ("movq %%rbp, %0" : "=r" (rbp) );
  77.  
  78. // sp points to the first qword below our stack frame.
  79. uint64_t* sp = (uint64_t*)(rsp - 8);
  80.  
  81. // Get stack base address, and compute how much memory is below us.
  82. uint64_t pre_stack_base = get_stack_base();
  83. uint64_t diff = rsp - pre_stack_base;
  84. uint64_t copy_size = argc >= 2 ? atoi(argv[1]) : diff / 8;
  85.  
  86. // Validate user size is within the stack.
  87. if(copy_size < 0 || copy_size > diff / 8) {
  88. printf("error: bad copy size (must be between 0 and %lu inclusive)\n", diff / 8);
  89. exit(EXIT_FAILURE);
  90. }
  91.  
  92. // Allocate buffers to hold stack memory.
  93. uint64_t* mem_before = checked_malloc(copy_size * 8);
  94. uint64_t* mem_after = checked_malloc(copy_size * 8);
  95.  
  96. // Copy stack memory before invocation.
  97. for(int i = 0; i < copy_size; ++i) {
  98. mem_before[i] = *(sp - i);
  99. }
  100.  
  101. // NOTE: Assuming the function is a leaf call.
  102. magic_function();
  103.  
  104. // Copy stack memory after invocation.
  105. for(int i = 0; i < copy_size; ++i) {
  106. mem_after[i] = *(sp - i);
  107. }
  108.  
  109. // Grab stack base after call to determine if it grew.
  110. uint64_t post_stack_base = get_stack_base();
  111.  
  112. // Compare stack memory and print it in a nice table.
  113. printf("offset | address | before | after | changed\n");
  114. printf("-------|----------------|--------------------|--------------------|--------\n");
  115.  
  116. int last_change = 0;
  117. for(int i = 0; i < copy_size; ++i) {
  118. bool changed = mem_before[i] != mem_after[i];
  119.  
  120. printf("%6d | %p | 0x%016lx | 0x%016lx | %s\n", i+1, sp - i, mem_before[i], mem_after[i], changed ? "yes" : "no");
  121.  
  122. if(changed) {
  123. last_change = i+1;
  124. }
  125. }
  126.  
  127. // Not really needed as we're about to exit, but good habit to always free anyway.
  128. free(mem_before);
  129. free(mem_after);
  130.  
  131. printf("\nrbp: 0x%016lx\n", rbp);
  132. printf("rsp: 0x%016lx\n", rsp);
  133. printf("stack base before call: 0x%016lx\n", pre_stack_base);
  134. printf("stack base after call: 0x%016lx\n", post_stack_base);
  135.  
  136. uint64_t estimated_size;
  137.  
  138. if(pre_stack_base != post_stack_base) {
  139. printf("stack base changed, assuming it grew to fit data\n");
  140. estimated_size = rsp - post_stack_base;
  141. } else {
  142. printf("no change in stack base, using last changed qword to determine size\n");
  143. estimated_size = last_change * 8;
  144. }
  145.  
  146. printf("estimated stack frame size: %lu bytes\n", estimated_size);
  147.  
  148. return EXIT_SUCCESS;
  149. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement