Use After Free Simply Explained

Jan. 27, 2021 // echel0n

  1. // gcc heap_uaf.c -o heap_uaf
  2. int main(){
  3. int DEBUG = 1;
  4. char *user_input = malloc(0x30);
  5. if(DEBUG) printf("user_input: %p\n", user_input);
  6. char *flag_content = malloc(0x30);
  7. if(DEBUG) printf("flag_content: %p\n", flag_content);
  8. printf("Name? ");
  9. scanf("%7s", user_input);
  10. printf("Hello %s!\n", user_input);
  11. /*
  12. *
  13. * If you uncomment free(), the output will be like this.
  14. *
  15. * Name? 1
  16. * Hello 1!
  17. * Auth: 0
  18. * Password? 2
  19. * Auth: 50
  20. * < flag output here
  21. * (fact: decimal 50 is representation of '2' string.)
  22. * Why it works?
  23. * Because when you free user_input
  24. * authenticated variable address will be the same address of user_input.
  25. * Which means, authenticated variable value will be changed and authentication will be broken as fuck.
  26. * */
  27. // comment this, it works as intented.
  28. free(user_input);
  29. long *authenticated = malloc(0x30);
  30. if(DEBUG) printf("authenticated: %p\n", authenticated);
  31. *authenticated = 0;
  32. if(DEBUG) printf("Authenticated value: %x\n", *authenticated);
  33. printf("Password? ");
  34. scanf("%7s", user_input);
  35. if (getuid() == 0 || strcmp(user_input, "hunter2") == 0){
  36. *authenticated = 1;
  37. }
  38. if(DEBUG) printf("Authenticated value: %x\n", *authenticated);
  39. if (*authenticated){
  40. open("/flag",0);
  41. read(3, flag_content, 0x30);
  42. write(1, flag_content, 0x30);
  43. }
  44. return 0;
  45. }
Disclosure
  1. #include <assert.h>
  2. int main(int argc, char *argv[])
  3. {
  4. char *password = malloc(0x10);
  5. char *name = malloc(0x10);
  6. printf("Password? ");
  7. scanf("%7s", password);
  8. assert(strcmp(password, "hunter2") == 0);
  9. free(password);
  10. printf("Name? ");
  11. scanf("%7s", name);
  12. printf("Hello %s!\n", name);
  13. // here comes the danger!
  14. free(name);
  15. printf("Goodbye, %s!\n", name);
  16. /*
  17. * You will likely see something garbage after "Goodbye!, " string.
  18. *
  19. * This garbage will be a heap address
  20. *
  21. * 00000000: 5061 7373 776f 7264 3f20 4e61 6d65 3f20 Password? Name?
  22. * 00000010: 4865 6c6c 6f20 4141 4141 4141 4121 0a47 Hello AAAAAAA!.G
  23. * 00000020: 6f6f 6462 7965 2c20 c579 7330 2956 210a oodbye, .ys0)V!.
  24. *
  25. * '0a' ignore this, this is \n
  26. * the part we interested in this: c579 7330 2956
  27. * This is a heap address in little endian
  28. * */
  29. return 0;
  30. }