ReverseEngineering – Telegram
ReverseEngineering
1.24K subscribers
40 photos
10 videos
55 files
666 links
Download Telegram
داینامیک اینسترومنت با Frida دیدن و لاگ کردن زمان اجرا

Frida بهت اجازه میده بدون تغییر فایل توی برنامه‌ ی در حال اجرا جا بزنید و تابعی رو hook کنید پارامتر ها رو ببینید یا لاگ کنید خیلی وقتا همین دیدن پارامترها کلی چیز رو روشن میکنه


میخواید بدونی برنامه موقع باز کردن فایل یا فرستادن درخواست شبکه چی میفرسته؟ با Frida یه اسکریپت کوچیک میزنید که وقتی تابع open یا send اجرا شد آدرس و داده‌ ها رو لاگ کنه بدون اینکه فایل رو دست بزنی میتونی جریان اجرا و ورودی‌ ها رو ببینید انگار گوشیت رو برای 5 ثانیه شنود میکنید ولی اخلاقی و برای تحلیل 😅

مثال:
یه برنامه ساده که فایل باز میکنه: با Frida hook کنید fopen یا open پارامتر مسیر فایل رو چاپ کنید و بعد اجازه بدید اجرا ادامه پیدا کنه فقط دیدن پارامترها نه تغییر رفتار

دیتکشن (تشخیص):

فراخوانی‌های ناگهانی API حساس با داد ه‌های عجیب مثلا رمزنگاری ناگهانی قبل از ارسال شبکه

تعداد بالای hook ها یا فراخوانی‌ های مکرر به توابع IO که میتونه نشونه obfuscation یا exfiltration باشه


میتیگشن (مدافع‌ها):

محقق: Frida رو داخل VM با شبکه محدود اجرا کنید

برای سازمان: telemetry که فراخوانی API حساس و رفتارهای غیر عادی runtime رو لاگ کنه اینطوری اگر کسی سعی کنه داده‌ ای لو بره یا رفتار مشکوکی باشه سریع عکس‌ العمل میگیرید


Dynamic Instrumentation with Frida Runtime Viewing and Logging

Frida lets you drop into a running program without changing the file and hook a function, view parameters, or log them often just seeing the parameters can tell you a lot

Want to know what your program is sending when it opens a file or makes a network request? With Frida you write a small noscript that logs the address and data when the open or send function is executed. Without touching the file, you can see the execution flow and inputs. It's like you're bugging your phone for 5 seconds, but ethically and for analysis 😅

Example:
A simple program that opens a file: Hook with Frida fopen or open, print the file path parameter, and then let it continue execution. Only see the parameters, not change the behavior

Detection:

Sudden calls to sensitive APIs with strange data, such as sudden encryption before sending it to the network

A high number of hooks or repeated calls to IO functions that can be a sign of obfuscation or exfiltration

Mitigations:
researchers Run Frida inside a VM with restricted network

For organizations:
telemetry that logs sensitive API calls and unusual runtime behaviors. This way, if someone tries to leak data or has suspicious behavior, you can react quickly.

@reverseengine
3
بازسازی struct ها و مرتب‌ سازی pseudocode

وقتی فهمیدید تابع چکاری میکنه مرحله بعدی اینه که بفهمید داده‌ها چطوری سازماندهی شدن یعنی struct‌ ها و type ها رو از روی الگوهای دسترسی بازسازی کنید تا کد قابل‌ فهم‌تر بشه


اگه توی دیس‌اسمبلر چند جا دیدید با offset مشابه به یه آدرس دسترسی پیدا میکنن خیلی احتمال داره که اونجا یه struct نشسته توی Ghidra یا IDA براش member بذارید اسم بزنید username, len, flags و ببینید کد چقدر براتون منطقی‌تر میشه همین تغییر کوچیک باعث میشه pseudocode مثل یه متن عادی بخونه نه یه سری دستور عجیب و غریب

مثال:
یه باینری که چند تابع از آدرسی با offsets 0x0, 0x4, 0x8 استفاده میکنه بردارید توی دی‌کامپایلر struct درست کنید با سه فیلد مثلا int, int, ptr و اسم‌گذاری کنید بعد دوباره pseudocode رو ببینید فهمیدن منطق تابع خیلی آسون تر میشه

دیتکشن (تشخیص):

دسترسی‌های ثابت و تکراری به یک آدرس با offset های مشابه

pattern هایی مثل base + 0x10, base + 0x14
که نشون‌ دهنده field ها هستن

این‌ها بهتون میگه این یه struct یا object هست


میتیگیشن (مدافع‌ها):

توسعه‌دهنده: از ساختارهای واضح و مستندسازی استفاده کنید تعریف struct و کامنت تا کسی دیگه مجبور نشه حدس بزنه

آنالیزور: نگه داشتن debug symbols در محیط توسعه یا build مخصوص آنالیز خیلی کمک میکنه قبل از انتشار strip‌ کردن باینری و منیج کردن symbol ها رو مدیریت کنید



Reconstructing structs and sorting pseudocode

Once you understand what the function does, the next step is to understand how the data is organized, i.e. reconstruct the structs and types from the access patterns to make the code more understandable

If you see several places in the disassembler where they access the same address with the same offset, it is very likely that there is a struct sitting there in Ghidra or IDA. Call it member, name it username, len, flags and see how much more logical the code becomes for you. This small change will make the pseudocode read like normal text, not a series of strange instructions

Example:

Take a binary that uses several functions with addresses with offsets 0x0, 0x4, 0x8, create a struct in the decompiler with three fields, for example int, int, ptr and name it. Then look at the pseudocode again. Understanding the logic of the function becomes much easier

Detection:

Fixed and repeated accesses to an address with offsets Similar

Patterns like base + 0x10, base + 0x14
which indicate fields

These tell you if this is a struct or an object

Mitigations (Defenders):

Developer: Use clear structures and documentation, struct definitions and comments so no one else has to guess

Analyzer: Keeping debug symbols in the development environment or build for analysis is very helpful. Strip the binary and manage the symbols before releasing.

@reverseengine
8
اگه حمایتا خوب بود کم کم میریم سمت باینری اکسپلویتیشن 🩶

If the supports is good, we will gradually move towards binary exploitation 🖤
🔥112
Forwarded from GO-TO CVE
CVE-2025-52287-week-75.pdf
5 MB
خوش اومدین به هفته 75 از برنامه GO-TO CVE این هفته به برسی اسیب پذیری روی wsus پرداختیم .

CVE : CVE-2025-52287
type : RCE
target : wsus
week : 75

#week_75
5
گزارش روند حملات سایبری در سال 2025 از mandiant

Cyberattack Trends Report 2025 From Mandiant

https://services.google.com/fh/files/misc/m-trends-2025-en.pdf

@FUZZ0x
4
روش کامپایل

فایل: vuln.c
قرار بدید داخل فولدری که تمرین میکنید

// vuln.c  VM ایزوله اجرا بشه

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

void vuln() {
    char buf[64];
    puts("Enter some text:");
    gets(buf);  //  فقط برای آموزش در عمل هرگز استفاده نکنید
    printf("You entered: %s\n", buf);
}

int main() {
    vuln();
    return 0;
}



🔧 کامپایل  دو حالت


نسخه ساده محافظت‌ ها غیر فعال

gcc -o vuln_plain vuln.c -fno-stack-protector -z execstack -no-pie -g


این نسخه برای دیدن رفتارهای پایه‌ ای overflow و آموزشه فقط داخل VM اجرا کنید


نسخه مقاوم‌تر پیش‌فرض کامپایلر

gcc -o vuln_hard vuln.c -g


این نسخه محافظت‌ های معمول canary, NX, PIE و ... فعالن و برای مقایسه استفاده میشن


چند تا نکته کوتاه:
gets()
نا امنه اینجا فقط برای نمایش overflow استفاده شده


Compile method

File: vuln.c
Place it in the folder where you are practicing

// vuln.c will run in an isolated VM

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

void vuln() {
char buf[64];
puts("Enter some text:");
gets(buf); // For training purposes only, never use in practice
printf("You entered: %s\n", buf);
}

int main() {
vuln();
return 0;
}


🔧 Two-mode compilation

Simple version with protections disabled

gcc -o vuln_plain vuln.c -fno-stack-protector -z execstack -no-pie -g


Run this version in a VM to see basic overflow behavior and tutorial

More robust version of the compiler default

gcc -o vuln_hard vuln.c -g


This version has the usual protections of canary, NX, PIE, etc. enabled and is used for comparison

A few quick notes:
gets()
Unsafe is used here only to demonstrate overflow

@reverseengine
3
اجرای سریع خارج از gdb چطور کرش میکنه

# ورودی کوتاه

نباید کرش کنه
echo "hello" | ./vuln_plain


ورودی خیلی طولانی  احتمالا کرش یا رفتار غیرعادی

python3 -c "print('A'*200)"  | ./vuln_plain


انتظار: با ورودی کوتاه برنامه معمولا خروجی میده با ورودی 200 بایت در vuln_plain احتمالا crash یا رفتار غیر معمول میبینید

باز کردن داخل gdb و گذاشتن breakpoint

gdb ./vuln_plain


داخل gdb:

(gdb) break vuln       
# ایست در تابع vuln


(gdb) run                  اجرا کنید #



# وقتی برنامه متوقف شد منتظر ورودی یا بعد از ارسال ورودی طولانی و کرش باشید:

(gdb) info register   # وضعیت رجیسترها



(gdb) x/40x $rsp   نمایش 40 #



qword
از آدرس RSP هگزادسیمال




(gdb) x/200xb $rsp

# نمایش 200 byte اطراف RSP بایت به بایت
(gdb) bt    # backtrace



(gdb) disassemble vuln
   # اسمبلی تابع vuln



نکته: اگر pwndbg نصب باشه به‌ جاش context و vmmap هم استفاده کنید:

(gdb) context

(gdb) vmmap



How does fast execution outside of gdb crash

# Short input

Shouldn't crash

echo "hello" | ./vuln_plain


Very long input  probably crash or unusual behavior

python3 -c "print('A'*200)"  |  ./vuln_plain


Wait: With short input the program usually outputs output. With 200 bytes of input in vuln_plain you may see a crash or unusual behavior

Opening inside gdb and setting a breakpoint

gdb ./vuln_plain


Inside gdb:

(gdb) break vuln   # stop in function


(gdb) run


Instead of context and vmmap
use:

(gdb) context

(gdb) vmmap


@reverseengine
4
Windows X86-64 System Call Table (XP/2003/Vista/7/8/10/11 and Server

https://j00ru.vexillium.org/syscalls/nt/64

@reverseengine
3
بخش ششم بافر اورفلو


درک دقیق کرش و ساختار فریم تابع در استک

در این بخش میخایم ببینیم وقتی بافر اورفلو باعث کرش میشه دقیقا در پشت‌ صحنه چه اتفاقی میوفته باید بعد از این قسمت
بفهمیم چرا بازنویسی داده در استک باعث تغییر آدرس برگشت میشه
فریم تابع چه اجزایی داره
و چطور میشه این اجزا رو با gdb دید و تحلیل کرد

وقتی یک تابع در C صدا زده میشه سیستم برای اون تابع فضایی در استک درست میکنه به این فضا میگیم فریم تابع هر فریم شامل این بخش‌ هاست

متغیرهای لوکال تابع

مقادیر پارامترها

saved RBP یا base pointer
برای برگشت

saved return address
که بعد از تموم شدن تابع بهش برمیگرده


اگر داده‌ ای بیشتر از اندازه در بافر لوکال نوشته بشه این مقادیر مهم در فریم بازنویسی میشن
و در نتیجه برنامه در return کرش میکنه یا به آدرس اشتباه میپره


این کد کمک میکنه تا فریم تابع و کرش رو ببینیم و در gdb تجزیه ش کنیم

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

void crash(char *input) {
char buffer[16];
printf("address of buffer: %p\n", buffer);
strcpy(buffer, input);
printf("done copying\n");
}

int main(int argc, char **argv) {
if (argc < 2) {
printf("usage: %s input\n", argv[0]);
return 1;
}
crash(argv[1]);
printf("returned safely\n");
return 0;
}



دستورات اجرا و تحلیل

gcc -g file4.c -o file4

gdb --args ./file4 $(python3 -c "print('A'*40)")


بعد از اجرای برنامه داخل gdb این مراحل رو انجام بدید

break crash

run

info frame

x/32x $rbp

x/32x $rsp

اینجا میبینید که بافر پایین‌ تر از saved RBP قرار داره
هر بایتی که از بافر بیرون بنویسید در اخر به saved RBP و بعد return address میرسه


برای مشاهده کرش

continue


برنامه با خطای segmentation fault کرش میکنه
با دستور زیر مسیر برگشت رو ببینید

backtrace


و با این دستور آخرین آدرس برگشتی رو چک کنید

info registers rip



توضیح کامل

در هنگام اجرای تابع crash سیستم اول RBP فعلی رو ذخیره میکنه
بعد RSP رو به پایین‌ تر منتقل میکنه تا فضای لازم برای متغیر های لوکال فراهم بشه
داخل این فضای جدید بافر قرار داره
وقتی ما داده‌ ای بزرگ‌ تر از اندازه بافر بنویسیم اول داده روی متغیر های لوکال مینویسن بعد روی RBP و بعد روی return address
در لحظه‌ای که تابع میخاد برگرده مقدار اشتباه از روی استک خونده میشه و RIP به آدرسی اشتباه پرش میکنه و همین باعث segmentation fault میشه


بخش جذاب

میتونید در gdb با این دستور تفاوت قبل و بعد از overflow رو ببینید


قبل از strcpy

x/32x $rbp-32


بعد از strcpy

x/32x $rbp-32


میبینید که بایت‌های A تمام فضای بین بافر تا return address رو پر کرده
این همون دلیل کرش برنامه هست

@reverseengine
3
Part 6 Buffer Overflow


Understanding the Crash and the Structure of the Function Frame on the Stack

In this part, we are going to see what exactly happens behind the scenes when a buffer overflow causes a crash. After this part, we should
understand why overwriting data on the stack changes the return address.
What are the components of a function frame?
And how can these components be viewed and analyzed with gdb.

When a function is called in C, the system creates a space on the stack for that function. We call this space the function frame. Each frame contains these parts.

Local variables of the function

Parameter values

Saved RBP or base pointer
for return

Saved return address
which the function returns to after the function completes

If more data is written to the local buffer than the limit, these important values ​​are overwritten in the frame
And as a result, the program crashes on return or jumps to the wrong address

This code helps us see the function frame and crash and analyze it in gdb

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

void crash(char *input) {
char buffer[16];
printf("address of buffer: %p\n", buffer);
strcpy(buffer, input);
printf("done copying\n");
}

int main(int argc, char **argv) {
if (argc < 2) {
printf("usage: %s input\n", argv[0]);
return 1;
}
crash(argv[1]);
printf("returned safely\n");
return 0;
}


Execution and analysis commands

gcc -g file4.c -o file4

gdb --args ./file4 $(python3 -c "print('A'*40)")


After running the program in gdb, perform these steps

break crash

run

info frame

x/32x $rbp

x/32x $rsp


Here you can see that the buffer is below the saved RBP

Every byte you write out of the buffer will eventually reach the saved RBP and then the return address

To view the crash

continue


The program crashes with a segmentation fault error

See the return path with the following command

backtrace


And check the last return address with this command

info registers rip


Full explanation

When executing the crash function, the system first saves the current RBP

Then it moves the RSP down to provide the necessary space for local variables

In this new buffer space, Yes
When we write data larger than the buffer size, first the data is written to local variables, then to RBP, and then to the return address
At the moment the function wants to return, the wrong value is read from the stack and RIP jumps to the wrong address, which causes a segmentation fault

Interesting part

You can see the difference before and after the overflow in gdb with this command

Before strcpy
x/32x $rbp-32


After strcpy
x/32x $rbp-32


You can see that the A bytes have filled all the space between the buffer and the return address

This is the reason for the program crash

@reverseengine
4