In this article, we will deal with the buffer overflow vulnerability in the heap, and also solve the 19th task from the site
pwnable.kr .
Organizational Information Especially for those who want to learn something new and develop in any of the areas of information and computer security, I will write and talk about the following categories:
- PWN;
- cryptography (Crypto);
- network technologies (Network);
- reverse (Reverse Engineering);
- steganography (Stegano);
- search and exploitation of WEB vulnerabilities.
In addition to this, I will share my experience in computer forensics, analysis of malware and firmware, attacks on wireless networks and local area networks, conducting pentests and writing exploits.
So that you can find out about new articles, software and other information, I created a
channel in Telegram and a
group to discuss any issues in the field of ICD. Also, I will personally consider your personal requests, questions, suggestions and recommendations
personally and will answer everyone .
All information is provided for educational purposes only. The author of this document does not bear any responsibility for any damage caused to anyone as a result of using knowledge and methods obtained as a result of studying this document.
How a bunch is organized
The memory can be busy (allocated) and free. The figure shows the dynamic memory.
- SSize - the size of the previous block of memory, provided that it is free.
- Size - the size of the given memory block, to which 2 status bits are added.
- Data - user data.
- Fd is a pointer to the next free block.
- Bk - pointer to the previous free block.
- Free - free memory.
Thus, no two free blocks can be neighbors. Plus, on the border of occupied and free system memory, there is a specially processed free W-block.
The representation of blocks in lists (baskets) is as follows.
The unlink method is used to remove a free block from the list.
void unlink(S, BK, FD){ BK = S->bk; FD = S->fd; FD->bk=BK; FD->fd=FD; }
Allocation and release of memory
Let's see how mmap works. The first step is to check the arrays of the required sizes (for example, 24 bytes). If there is a necessary block, then it is separated using unlink.
In the second step, if this block is large enough, then it is divided into two parts. The first part is allocated, and the second is redistributed to another array.
In the third step, if the block of the required size has not been allocated, then the W-block is checked. If he satisfies, then steps two are held with him. If the W-block was small, then sbrk () and mmap () are used to expand the available memory. The Free method is completely opposite to mmap.
Heap buffer overflow
A heap overflow is a type of buffer overflow that occurs in the heap data area. Memory on the heap is dynamically allocated by the application at run time and usually contains program data. Exploitation is performed by corrupting this data in a special way so that the application overwrites internal structures, such as pointers to a linked list. The canonical heap overflow method overwrites the dynamic memory allocation relationship (for example, malloc metadata) and uses pointer exchange to rewrite a pointer to a program function.
As an example, in the Unlink function, using FD-> bk, you can change the value of an arbitrary word in memory. For example, put the shellcode to change the GOT address. An example of overflow will be an example.
Unlink job solution
We click on the first icon with the signature unlink, and we are told that we need to connect via SSH with the password guest.
When connected, we see the corresponding banner.
Let's find out what files are on the server, as well as what rights we have.
Let's see the source code.
So we have object B associated with objects A and C. Then the object A is entered and filled. Having the objects A - B - C connected and controlling the filling of A, we can overflow the heap and rewrite objects B and C. We need to find a way to exploit the vulnerability. Let's look through gdb.
Thus, we can write the shellcode and rewrite the return address from main to our shellcode. The return address falls into esp from the ecx register, where it feeds from ebp-4. Disassembling the unlink function, we notice that ebp-4 can be controlled by user input.
We will analyze how our objects are located in memory and how the unlink function works. Each object occupies 16 bytes in memory (4 for pointers and 8 for buffers).
The allocation of memory for objects occurs in the lines main + 38, main + 54 and main + 70. Before each call, the stack pointer (esp) increases by 16 and decreases by 12, after which 16 bytes are reserved.
That is, there are 4 bytes between structures.
Next is the linking and linking of objects.
Thus, we need that when returning from the function, the address will go to the location heap + 12, which will transfer control to the address where the shellcode is located.
from pwn import * s = ssh("unlink", "pwnable.kr", password="guest", port=2222) ex = s.process("./unlink") shell_address = p32(0x80484eb) ans = ex.recv().split("\n") stack_addr = p32(int(ans[0].split(" ")[5],16) + 16) heap_addr = p32(int(ans[1].split(" ")[5],16) + 12) payload = shell_address + "A"*12 + heap_addr + stack_addr ex.sendline(payload) ex.interactive()
We get the shell, read the flag, get 10 points.
You can join us on
Telegram . Next time we’ll deal with heap overflow.