Analyze 64 bit ROP Stack with IDA

I would like to continue my previous tutorial post on how to analyze ROP stack with IDA. Today, I am going to share a simple tutorial for 64 bit application including finding the ROP with tools ROPgadget.py

The function calling convention is quite different to the 32 bit application where function arguments are passed in certain registers

  1. RDI
  2. RSI
  3. RDX
  4. RCX
  5. R8
  6. R9

then any leftover arguments are pushed onto the stack in reverse order, as in cdecl.

In order to call a function with arguments, we need to be able to control the arguments by finding operation in the application such as pop rdi; ret or pop rsi; pop r15; ret

ROPgadget

We can use the ROPgadget.py to find sequence of operation that are able to help us manipulating the call. You can download the python script from https://github.com/JonathanSalwan/ROPgadget

I suggest to use powershell to run the ROPgadget.py to enable us doing string-filter which make us easier to find the gadget

PS C:\Apps\ROPgadget-master> python .\ROPgadget.py --binary .\ROPTest.exe | select-string -Pattern 'pop rdi'
0x0000000140014553 : pop rdi ; add byte ptr [rax], al ; xor edx, edx ; call 0x14001100a
0x000000014001394b : pop rdi ; pop r13 ; pop r12 ; pop rsi ; ret
0x0000000140013bfc : pop rdi ; pop rbp ; pop rbx ; ret
0x00000001400136c1 : pop rdi ; pop rsi ; pop rbp ; ret
0x0000000140014d40 : pop rdi ; pop rsi ; pop rbx ; pop rbp ; ret
0x0000000140012591 : pop rdi ; pop rsi ; ret
0x000000014001291c : pop rdi ; ret
0x0000000140013bf7 : pop rsi ; pop r13 ; pop r12 ; pop rdi ; pop rbp ; pop rbx ; ret
0x0000000140014d3b : pop rsi ; pop r13 ; pop r12 ; pop rdi ; pop rsi ; pop rbx ; pop rbp ; ret
0x00000001400136c0 : pop rsi ; pop rdi ; pop rsi ; pop rbp ; ret
0x0000000140013039 : pop rsp ; and al, 0x30 ; add rsp, 0x20 ; pop rdi ; ret
0x0000000140013bfb : pop rsp ; pop rdi ; pop rbp ; pop rbx ; ret
0x0000000140014d3f : pop rsp ; pop rdi ; pop rsi ; pop rbx ; pop rbp ; ret
0x0000000140013e2a : push rax ; cmovs eax, ecx ; add rsp, 0x30 ; pop rdi ; ret

We can see that from the above output that we can use that address reference for our call manipulation. Lets use pop rdi; ret which has address on 0x000000014001291c

If we try to find that address on IDA

But remember that we need to recalculate the address so that it matches with the address in memory after considering the base address of the binary

You can also be able to find the operation pop rdi by using IDA text search functionality

Sample C code application

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* overwrite = "Rio is Here";

void printMe_1() {
    printf("Function Print Me 1");
}

void printMe_2() {
    printf("Function Print Me 2");
}

void printMe_3() {
    char* actual = "actual value";
    printf("Function Print Me 3 %s \n", actual);
}

void check() {
    printMe_3();
    printf("Call Me Please Check \n");
}


int main(int argc, char** argv) {
    
    check();
    printf("Exiting...\n");
    exit(0);
}

Manipulating the Stack

I put a break point in the check function. We can see that the return address is going back to the main function

The return address that we need to overwrite with pop rdi address. Since the operation is pop rdi ; return then we need to arrange the stack to be like this [ADDRESS of WIDGET] + [ADDRESS of PARAMETER] + [ADDRESS of FUNCTION]

00007FF65CF0291C –> Address of WIDGET
00007FF65CF09BB0 –> Address of Parameter
00007FF65CF018D0 –> Address of Function

Jump to Widget

Now we are in widget operator

The pop rdi will push the aRioIsHere will be pushed into RDI

We can see that now RDI is pointing to our string RioIsHere address

When the operator reach ret after executirng pop rdi then it will check what is on the top of the stack. We know that we have overwritten with the function that we are going to go which is printMe_1

So when when we move further then we can see the flow will jump into our function

We can see that now we are in the printMe_1 function. With the help of the ROP Widget we can actually change the flow and parameter of the function call by manipulating the stack

We can manipulate the stack by exploiting buffer overflow vulnerability in the application.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s