intmenu() { puts("Choose a function to allocate heap memory:"); puts("1. malloc"); puts("2. calloc"); puts("3. realloc"); returnprintf("Enter your choice: "); }
v4 = __readfsqword(0x28u); ptr = 0; __isoc99_scanf("%d", &n4); if ( n4 == 2 ) { printf("Enter the size to allocate using calloc: "); __isoc99_scanf("%lu", &size); ptr = calloc(1u, size); } elseif ( n4 > 2 ) { if ( n4 != 3 ) { if ( n4 == 4 ) { printf("Here is you want: "); system("cat /ctfshow_flag"); } goto LABEL_12; } printf("Enter the size to allocate using realloc: "); __isoc99_scanf("%lu", &size); ptr = realloc(ptr, size); } else { if ( n4 != 1 ) { LABEL_12: puts("Invalid choice."); return __readfsqword(0x28u) ^ v4; } printf("Enter the size to allocate using malloc: "); __isoc99_scanf("%lu", &size); ptr = malloc(size); } if ( ptr ) printf("Memory allocated at address: %p\n", ptr); else puts("Memory allocation failed."); return __readfsqword(0x28u) ^ v4; }
直接输4就好了
$ ./pwn * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Heap_Exploitation * Site : https://ctf.show/ * Hint : Learn how to allocate heap ! * ************************************* Choose a function to allocate heap memory: 1. malloc 2. calloc 3. realloc Enter your choice: 4 Here is you want: flag{just_test_my_process} Invalid choice.
$ ./pwn * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Heap_Exploitation * Site : https://ctf.show/ * Hint : sbrk and brk example ! * ************************************* sbrk example:36 Program Break Location1:0x6263b987f000 a Program Break Location2:0x6263b9880000 Program Break Location3:0x6263b987f000 a flag{just_test_my_process}
getpid():
pid_tgetpid(void);
作用:获取当前进程的PID
返回值:
返回值:
成功:返回调用进程的 PID(通常是一个整数)[数据类型为 pid_t(通常是一个整数类型)]
失败:不会失败
特点:
常用于调试、日志、信号处理等
如果一个进程 fork 出子进程,子进程有新的 PID
sbrk()函数:
void *sbrk(intptr_t increment);
作用:
获取或调整当前进程的 数据段(堆)的末尾地址(program break)
increment 表示要增加或减少的字节数
参数:
increment:
0:返回当前堆顶地址
正数:扩展堆,返回原堆顶
负数:收缩堆,返回原堆顶
返回值:
成功:返回调用前的堆顶地址(当前堆的末尾)
失败:返回 (void*) -1,并设置 errno
brk函数:
int brk(void *end_data_segment);
作用:设置进程的数据段(堆)的末尾地址
参数:
end_data_segment:新的堆顶地址
返回值
成功:返回 0
失败:返回 -1 并设置 errno
特点
直接把堆顶设置到某个位置(比 sbrk 更直接)
一般 malloc 内部会用 brk 来向操作系统申请或收缩堆
pwn138
Hint:Private anonymous mapping example
// local variable allocation has failed, the output may be wrong! int __fastcall main(int argc, constchar **argv, constchar **envp) { __pid_t pid; // eax void *addr; // [rsp+8h] [rbp-8h]
$ ./pwn * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Heap_Exploitation * Site : https://ctf.show/ * Hint : Private anonymous mapping example using mmap syscall ! * ************************************* Welcome to private anonymous mapping example::PID:42 Before mmap a After mmap After munmap a flag{just_test_my_process}
mmap 函数:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
作用:mmap() 是一个 Linux 系统调用,用于在进程的虚拟地址空间中映射一段内存区域。映射区域可以来自文件,也可以是匿名内存(不依赖文件,直接向内核申请内存)。在现代 malloc 实现中,大块内存通常通过 mmap 分配
v8 = __readfsqword(0x28u); init(argc, argv, envp); logo(); pid = getpid(); printf("Welcome to per thread arena example::%d\n", pid); puts("Before malloc in main thread"); getchar(); ptr = malloc(0x3E8u); puts("After malloc and before free in main thread"); getchar(); free(ptr); puts("After free in main thread"); getchar(); if ( pthread_create(&newthread, 0, threadFunc, 0) ) { puts("Thread creation error"); return-1; } elseif ( pthread_join(newthread, &thread_return) ) { puts("Thread join error"); return-1; } else { system("cat /ctfshow_flag"); return0; } }
输入3次即可得到flag
$ ./pwn * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Heap_Exploitation * Site : https://ctf.show/ * Hint : Per thread arena example. ! * ************************************* Welcome to per thread arena example::54 Before malloc in main thread a After malloc and before free in main thread After free in main thread a Before malloc in thread 1 After malloc and before free in thread 1 a After free in thread 1 flag{just_test_my_process}