2

Recent RDP vulnerability and exploits have mentioned the use of heap shaping technique. Can anyone please explain in details what is actually involved in using this tactic.

Thanks

2

Heap shaping (also called heap grooming, for a more passive approach) is the slightly more intelligent sibling of heap spraying while developing exploits. Therefore, to properly explain heap shaping one must first be familiar with heap spraying.

heap spraying

Heap spraying is the act of intentionally filling (spraying) a target process's heap space with recurring/sequential data, using an external attack primitive.

Say for example, you've found a uninitialized-variable bug, where a variable is not initialized when it should, and is then used in a manner that could be dangerous depending on it's the actual value.

An example might make it clearer:

typedef struct __struct_cmd {
    int type;
    char shell_cmd[1024];
} struct_cmd;

void safe_cmd(struct_cmd* cmd)
{
    switch (cmd->type)
    {
    case CMD_1:
        strcpy(cmd->shell_cmd, SAFE_CMD1);
        break;
    case CMD_2:
        strcpy(cmd->shell_cmd, SAFE_CMD2);
        break;
    }
    system(cmd->shell_cmd);
}

In the above example, it's easy to notice that if a user provides any value other than CMD_1 or CMD_2 for cmd.type, shell_cmd will not be uninitialized and an unknown value will be passed on to the lucrative system call.

Being able to set cmd->shell_cmd to a specific value that is a valid (and malicious) shell command will potentially give us code execution on the target. Simply put, heap spraying is the act of getting a lot of heap memory space filled with the specific shell command we'd like to execute.

heap shaping

Now that was a relatively trivial case, and quite frequently heap spraying/shaping are used to exploit memory corruption bugs but that's irrelevant. Usually, you'd be addressing many more constraints to successfully exploit a memory corruption, and "filling the heap with data" simply won't be enough.

Double-free and use-after-free bugs will require specific objects/structs be allocated at the same space a different object previously reside in. You'd then need to make sure the heap has a specific shape, in a way, so that a different object will "fit" into a coalescing heap (or high fragmentation heap, as opposed to low fragmentation heap). You may need to make sure a specific instance you control through a primitive is allocated in the right spot. Getting the heap to be in that specific way is what's called "heap shaping"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.