Return Focused Shows and ret 2 libc Strike


Return-Oriented Shows (ROP) is an exploitation technique made use of to bypass safety defenses like Data Execution Avoidance (DEP) It enables an opponent to execute approximate code on a target system without infusing new executable code , by chaining together existing code snippets from an at risk binary or crammed libraries.

The basis of return-oriented shows is chaining with each other small portions of code currently existing within the binary itself in such a way as to do what we want. For example, obtaining a shell.

ret 2 libc (Return-to-libc) is a classic assault technique utilized in binary exploitation to bypass Information Execution Avoidance (DEP) by rerouting program execution to existing libc features (e.g., system() , execve()

  • The ret 2 libc is ROP with a little difference. The difference is that these little pieces of code which we’ll be making use of are in the dynamically connected c collection called libc.
  • Why do we make use of libc? Well, it’s already linked to our binary, and libc has a few of the features which are interesting to us. Among the functions which work to us is called “system” which allows us perform anything passed to it.
  • Now, what if I inform you that in libc, there is likewise a string worth that resembles this: “/ bin/sh”. I believe you currently know where this is going.
  • All we have to do is develop an ROP chain (little chunks of code chained together) that passes the “/ bin/sh” string as the disagreement to the system function and after that call this feature.

I took the help of TryHackMe room for the instance attack scenario: https://tryhackme.com/room/ret 2 libc

There’s an executable binary called exploit_me, which we will evaluate.

Allow’s run the data.

It takes a string as input and displays it back to you as your name. When you enter a lot of A’s, it creates a segmentation fault. It implies there’s barrier overflow.

If we examine the file kind, we discover that we are dealing with a 64 bit binary.

The following point we require to determine is the offset of this overflow.

We’ll make use of gdb with gef plugin.

Open up gdb utilizing:

gdb exploit_me

We’ll utilize ‘pattern produce’ to generate the pattern that we’ll be providing to our binary as an input.

Duplicate the pattern and kind ‘r’ to run the program. Offer this pattern as input.

All we need to do is read the data from the $RSP register and utilize it in the pattern search command. We can do that quickly with pattern search $rsp.

Keep in mind: If we were collaborating with a 32 -little bit binary, we ‘d look for the data for our pattern search in the $RIP register.

So the offset is 18

If you run checksec on exploit_me, you’ll find the complying with info:

  • The binary has Partial RELRO, which indicates that the international countered table reads and writable.
  • Pile canary isn’t located, which suggests that if there is any kind of buffer overflow, we can just abuse it.
  • NX is made it possible for, which indicates that we can not carry out custom-made shellcode from the pile, and it’s additionally the main reason we’re making use of the ret 2 libc attack.
  • PIE is impaired, which implies that our binary will constantly begin at the address 0x 400000 and won’t be influenced by ASLR

Address Area Layout Randomization:

Address space format randomization is a technique involved in preventing exploitation of memory by randomly arranging the address area settings of key information locations of procedures and the settings of the stack, heap and collections.

Firstly, we can inspect if ASLR is activated in our VM with the command:

Number 2 means complete randomization. This means the ASLR is turned on.

The binary isn’t impacted due to the fact that there’s no PIE security, however things which is being affected is the libc, which is dynamically connected to our binary and is compulsory for our ret 2 libc assault to function.

As a result of ASLR, we now can not call the system feature due to the fact that we do not understand the address of this feature in libc.

And also if we search for the address of the system function when we run the program, the next time we run it, it’ll be a various address. So exactly how do we bypass this?

Global Offset Table (GOT):

The worldwide balanced out table is a section inside a program that holds addresses of dynamically connected features. The majority of programs do not consist of every feature they use to reduce binary size. Instead, typical features, like those in libc, are “linked” into the program.

All dynamic libraries are loaded right into memory in addition to the main program at launch; nevertheless, functions aren’t mapped to their real code until they’re initially called.

Yet, after these functions are asked for the first time, their genuine addresses are “conserved” in the area of the program called.got.plt.

ASLR Bypass

We need to leak the address of any kind of feature which is in libc and is being utilized in our binary (so it’ll be conserved in got.plt

We require some function that can print worths and can take a reminder as an argument. The best functions for this are places and printf

So what we can do now is to call puts and, as a debate, pass a tip to any kind of function that’s inside got.plt

As an example: If we call places and as a debate, we pass the address of the setbuf function inside of. got.plt area, after that we must have dripped the genuine address of the sefbuf function inside a libc. And when we have this leakage, we can determine the base address of the libc.

Libc base address => > Start of the c library in memory

And when we have this base address, each time the binary is being run, the address is the same as it would have been when ASLR was shut off, and from that, we can determine offsets for each feature inside of libc, or we can also rebase our libc.

Allow’s analyze our binary in Ghidra

The binary uses ‘gets’ to review customer input, which is prone due to the fact that it doesn’t examine input length. The barrier size is 10 bytes.

We know that our overflow balanced out is a little bit larger than that. It’s because, in memory between our barrier and instruction guideline, there is various other data that we likewise need to overflow.

There’s an additional actually intriguing thing, and that’s the setuid( 0) function.

Discovering the leakage feature

Currently allow’s find our leak feature.

In the left upper corner, there’s a home window called Program Trees, where we can see areas of the program. We have an interest in the section called got.plt that we went over earlier.

Program Trees -> > exploit_me ->>. got.plt

When you double click that, you should see which features remain in the got.plt area.

Left wing, you can see an address alongside each feature, which address is exactly the one that we’ll be passing to the puts feature as a disagreement.

We can pick any type of feature from these 3 (places, printf, obtains); it doesn’t matter which feature as long as we bear in mind which we’ve chosen.

We’ll use gets as leak function. Currently we have our argument ready, and the only thing we need to do is pass it to the places function. Yet how do we call puts?

We can locate places in the treatment link table (PLT) and call it from there. We require to understand where to discover this PLT section in Ghidra.

Exploit:

Component 1:

Importing collection and specifying inputs

  #!/ usr/bin/env python 3 
from pwn import *
context.binary = binary='./ exploit_me'
fairy = ELF(binary)
rop = ROP(fairy)
libc = ELF('/ lib/x 86 _ 64 -linux-gnu/libc. so. 6)
p = process()

On the initial line, we’re appointing the exploit_me binary into the binary variable and afterwards including this binary to the context. Context is a global variable that instantly sets setups (like architecture, running system, bit-width) for our binary. So later on, when we’ll use our binary variable, we don’t have to define every setting by hand.

On the following line, we’re producing a variable called fairy so that we can control it with our binary as an ELF object inside of our manuscript. Once the variable has actually been produced, we utilize that fairy variable to produce an ROP item called rop We’ll make use of both of these variables later on in the code.

Next, we’re creating a variable called libc and appointing the full course of libc to it. Our binary will certainly be utilizing libc as a fairy object. If you don’t know just how to discover which libc our binary is utilizing, you can do that with the command ldd: ldd exploit_me

The last point we’re doing is generating our binary as a process. You can see that we didn’t define which process to generate; that’s due to the fact that we added our binary right into the context. Now we’ll start developing the ROP chain to leakage the gets feature.

Part 2:

First ROP chain

  cushioning = b'A'* 18 
payload = cushioning
haul += p 64 (rop.find _ gadget( ['pop rdi', 'ret'] [0]
payload += p 64 (elf.got.gets)
payload += p 64 (elf.plt.puts)
haul += p 64 (elf.symbols.main)

Currently we have every little thing ready to begin the very first ROP chain to leak the libc base address.

In the ROP chain, the initial thing we do is create the variable payload and appoint our overflow balanced out (=padding) to it.

The standard logic of the ROP leakage chain is as complies with:

  1. Standing out the $RDI register for our disagreement
  2. Loading the $RDI register with the address of the obtains feature
  3. Executing the puts function with loaded disagreement
  4. Returning to the major program with currently leaked feature

Currently allow’s damage down every function in this part so you can completely understand what is taking place.

p 64 ()

  • Returns the byte string from the data passed in the argument.

rop.find _ gadget( ['pop rdi', 'ret'] [0]

  • Returns a variety of all addresses in memory where the guidelines [‘pop rdi’, ‘ret’] happen, and considering that we only need the first one, we define [0] for the first value in the selection.

elf.got.gets

  • Returns the address of the obtains functions from the.got.plt area, which we went over in the previous job.

elf.plt.puts

  • Returns the address of the puts function from the.plt area.

elf.symbols.main

  • Returns the address of the major feature.

Since we have crafted the payload for our leakage, we need to send the payload, then obtain and refine the returned leak of the function.

Component 3:

Sending out and processing

  p.recvline() 
p.sendline(payload)
p.recvline()
leak = u 64 (p.recvline(). strip(). ljust( 8, b'\ 0'))
p.recvline()

In this part, you can see that we’re using p.recvline() multiple times. With this feature, we’re getting rid of any unneeded lines which may be printed in our incurable when running the exploit. We’re trying to refine the input to ensure that you only see the dripped address being outputted.

With p.sendline(haul) we’re sending our produced leak payload. And the last thing we require to do is process the leakage into a functional style. In its original state, the leak is a byte string, and we require it as a typical address, to make sure that suggests we need to convert it in some way.

We do that conversion with this line:

leakage = u 64 (p.recvline(). strip(). ljust( 8, b'\ 0'))

u 64 ()

  • So with this function, we’re unboxing the byte string. However below comes one little problem, which is addressed by the following feature.

ljust( 8, b'\ 0'))

  • One concern below is that the u 64 () function can not unload a byte string that isn’t precisely 64 little bits long (= 8 bytes). Since our address does not been available in this dimension, padding is called for.
  • This cushioning is done by adding additional void bytes (before we unbox it) to the beginning of the string so that we have a byte string that is exactly 64 little bits (= 8 bytes) long.
  • The initial debate is the last length of the byte string. In our case, it’s 8
  • The 2nd disagreement is the byte that is being prefixed up until the byte string is precisely 8 bytes long. In our case, it’s the void byte.

strip()

  • At the end of our byte string is the new line personality \ n , which we want to eliminate, and the strip feature does exactly that.

p.recvline()

  • Is just reviewing the first byte string.

Part 4:

Rebase of libc

  log.info(f'Gets leakage => > web link ') 
libc.address = leak - libc.symbols.gets
log.info(f'Libc base => > part ')

In this publishing, we’re refined our leak And then address. a bit there’s mathematics of associated with calculating Allow the base address.

clarify me Visualize it.

  • leak our alters as some address that whenever point. The only we understand that regarding comes from it is that this address gets the function intend to. We determine will the base address of the libc, which also various be every time And now.
  • intriguing comes the part variety. The between gets the base address and the function always is exact same the considering that. And treat we can simply addresses like numbers, we can deduct obtains the address of the feature leakage from our gives.
  • This currently us the base address of the linked print libc, and we value this out to inspect ‘ve if weevery little thing done properly We understand.
  • every little thing appropriate is ends when the base address three with Now 0’s.

have when we determined just how avert to security ASLR continue, we can actual with the make use of ret 2 libc Component.

Second 5:

haul ROP chain

  cushioning = payload 
device += p 64 (rop.find _ payload( ['pop rdi', 'ret'] [0]
next += p 64 (payload(libc.search(b'/ bin/sh')))
gadget += p 64 (rop.find _ payload( ['ret'] [0]
start += p 64 (libc.symbols.system)

We can creating by an additional payload reuse. And we can haul the variable once again for this. So start, we can assigning by currently the developed extra padding start as the haul of the trigger to barrier the standard overflow.

The reasoning generate of the “covering Standing out” ROP chain:

  1. debate the $RDI register for our Filling.
  2. guideline the $RDI register with the byte string “/ bin/sh”.
  3. Ret stack is for the placement simply (consider require this as something that we otherwise to do; issues, some may take place Performing).
  4. feature the system a crammed with argument Currently.

allow damage’s feature down every part in this completely so you can comprehend taking place what is ‘ve.

Wealready discussed features the p 64 () and find_gadget() skip, so I’ll for every these.

libc.search(b'/ bin/sh')

  • Returns the iterator online next address that matches the byte string “/ bin/sh”.

Feature()

  • following returns the “established” iterator from the suits function.

libc.symbols.system

  • Returns the address of the system within linked our Considering that libc.
  • initially we specified an ELF the libc variable as item later and initial rebased this libc with our now ROP chain, we can function call the system Currently right from the libc.

everything we have ultimately all set let, so continue’s into last the component send out, where we’ll 2nd the payload get and shell an interactive Part.

Sending out 6:

last the payload payload

  p.sendline(Here) 
p.recvline()
p.interactive()

simply we’re sending 2nd the payload clearing out and unneeded some outcome starts. The last line setting the interactive interact, so we can created with the covering everything if went well final.

The manuscript resembles manuscript this:

Run the get and you’ll origin the Many thanks flag!

reviewing for Resource!

link link

Leave a Reply

Your email address will not be published. Required fields are marked *