Explorer, 2016/05/30 10:53

0 x00 preface


Three white caps finally came up with a PWN challenge. Finally, I can let this kind of web chicken get a few cat money. And this topic out of the mind, behind the use of a ring buckle a ring, the quality is very high.

Now let’s share some detailed ideas.

Attach the original file: VMs.zip

0x01 Code analysis


The first step in doing PWN problems is to analyze the code and look for bugs. This program code flow is not very long, the total number of functions is only a dozen, so there are not many problems in the analysis of the code.

The structure of the body

This is the Vulnerability structure restored after analysis. It is also the main structure for storing data in a program. And of course the most important thing is that there’s a pointer in the structure. Once overwritten, it can be used for arbitrary reading and writing

00000000 Vulnerability   struc ; (sizeof=0x60, mappedto_1)
00000000 rank            dq ?
00000008 titleSize       dq ?
00000010 detailLen       dq ?
00000018 title           db 64 dup(?)
00000058 detail          dq ?                    ; offset
00000060 Vulnerability   ends
Copy the code

leaky

There are two major vulnerabilities in the application. The first is that edit does not validate the IN_use bit when modifying the Vulnerability structure. So there are cases where memory can be modified even after it has been freed. The so-called Use after Free vulnerability

With a little analysis, it’s easy to spot the UAF bug

The second loophole is more subtle. When adding Vulnerability and edit modifies Vulnerability, if a negative rank bit is entered, the application will skip the rank field instead of assigning a value to it. We can use this to leak information on the heap. Because this is the only place in the whole program that doesn’t destroy the original data on the heap. The rest of the Vulnerability structure forces changes to the in-memory data and cannot be used to leak information

The problem maker dug a hole

The problem maker dug three big holes in the whole problem for people to jump into. To get the shells, you need to bypass them one by one.

1. Encrypt all heap Pointers

Either the pointer to the Vulnerability of the BSS segment or the pointer to the detail in the Vulnerability structure is stored with a random number or later. Therefore, uAF cannot directly modify the pointer to achieve arbitrary address reading and writing.

So we must first find a way to get the random number or use, otherwise we can not complete the use.

2. The heap pointer check function

Before the program reads or writes the detail memory through the pointer, there is a function called check to check the validity of the heap pointer, and if the check is incorrect, the program will exit

Fortunately, this check is not as strict as that. Generally speaking, as long as the Vulnerability pointer is less than or equal to the detail pointer, there is a high probability of passing the check. When tested in practice, the entire attack usually succeeds in less than 20 attempts

3. The FULL RELRO protection

Checksec to see that FULL RELRO is enabled, which means we cannot modify the global offset table. Even arbitrary reads and writes implemented through UAF have no control over the EIP. There are no obvious function Pointers in memory that can be overridden.

Here I implement the final call to system by overriding free_hook. Here is the relevant code. You can see that the free function can be hooked to call our custom function. As long as we change __free_hook to the address of the system function, we can get the shell

2926 __libc_free (void *mem) 2927 { 2928 mstate ar_ptr; 2929 mchunkptr p; /* chunk corresponding to mem */ 2930 2931 void (*hook) (void *, const void *) 2932 = atomic_forced_read (__free_hook); 2933 if (__builtin_expect (hook ! = NULL, 0)) 2934 { 2935 (*hook)(mem, RETURN_ADDRESS (0)); 2936 return; 2937}... 2962 } 2963 libc_hidden_def (__libc_free)Copy the code

0x02 Detailed Utilization Process


The first step is to leak out random numbers for or. It takes some sleazy thinking to build a heap.

1. Obtain the heap address

First, we need to know the exact address of the heap. We can do this in Leak, a linked list pointer in heap management. The Vulnerability structure’s Rank field is exactly where the linked list pointer is stored. As mentioned earlier, we can leak the heap address through rank as long as we don’t write the rank value when we add.

2. Use fastbin vulnerability to control malloc memory address

We know about fastbin’s one-way linked list. With UAF, our rank field can override the single necklace pointer. To control the address of the next malloc. And we already know the address of the heap. So we can control Malloc. Make the rank field of the newly assigned Vulnerability structure overlap with the detail pointer of another Vulnerability. This allows us to leak and modify the detail field. And combine that with the heap address you just got. We can also work backwards to figure out the values used for random numbers.

At this point, we have implemented reading and writing to arbitrary addresses

3. Leak the LIBC base address

This is the easy one. Because normal bin is managed through a bidirectional linked list. The heads of bidirectional lists are stored in liBC. So simply freeing a large chunk of memory at random on the heap produces a pointer to the LIBC. In the process of my utilization. There happens to be a pointer on the heap that leaks out and then calculates the LIBC base address.

4. Write free_hook

Use IDA to check liBC to find the address of free_hook in liBC

The last actual address is 0x3C0A10. Just write in the address of the calculated system function. Finally, find a piece of memory and write /bin/sh and take it to free to complete the whole utilization process

The blood as a souvenir