ReverseEngineering – Telegram
ReverseEngineering
1.24K subscribers
40 photos
10 videos
55 files
666 links
Download Telegram
A Linux Toolkit for Reverse-Engineering and Analyzing Malware

https://remnux.org

@reverseengine
1
Local Variables روی استک

وقتی تابع متغیر محلی داره کامپایلر اون رو روی استک میزاره

ساختار فریم استک کامل

بعد از اجرای prologue:

push rbp
mov rbp, rsp
sub rsp, X ; ایجاد فضا برای متغیرهای محلی


ساختار میشه:

[ rbp+16 ] آرگومان سوم
[ rbp+8 ] آدرس برگشت
[ rbp+0 ] RBP قبلی
[ rbp-8 ] متغیر محلی 1
[ rbp-16 ] متغیر محلی 2




مثال:

int foo(int x) {
int t = x + 3;
return t * 2;
}


اسمبلی:

foo:
push rbp
mov rbp, rsp
sub rsp, 16 ; فضای متغیر محلی

mov DWORD PTR [rbp-4], edi ; t = x
add DWORD PTR [rbp-4], 3 ; t = x + 3

mov eax, DWORD PTR [rbp-4]
add eax, eax ; eax = t * 2

leave
ret


نکات مهم:

متغیر t روی استک قرار میگیره آدرسش rbp-4

چون int هست سایز 4 بایت

eax خروجی تابع



Local Variables on the Stack

When a function has a local variable, the compiler pushes it onto the stack

Complete stack frame structure

After executing the prologue:

push rbp
mov rbp, rsp
sub rsp, X ; Create space for local variables


The structure becomes:

[ rbp+16 ] Third argument
[ rbp+8 ] Return address
[ rbp+0 ] Previous RBP
[ rbp-8 ] Local variable 1
[ rbp-16 ] Local variable 2


Example:

int foo(int x) {

int t = x + 3;

return t * 2;
}


Assembly:

foo:

push rbp
mov rbp, rsp
sub rsp, 16 ; Local variable space

mov DWORD PTR [rbp-4], edi ; t = x
add DWORD PTR [rbp-4], 3 ; t = x + 3

mov eax, DWORD PTR [rbp-4]

add eax, eax ; eax = t * 2

leave
ret


Important notes:

The variable t is placed on the stack, its address is rbp-4

Because it is an int, its size is 4 bytes

eax is the output of the function

@reverseengine
👍4
ReverseEngineering
🔹 Red Zone در سیستم‌ های x86-64 بر اساس ABI لینوکس پایین RSP اشاره‌گر استک یک محدوده‌ی 160 بایتی وجود داره که به اون Red Zone میگن 🔸 این فضا مخصوص برای چیه؟ کامپایلر اجازه داره بدون تغییر RSP از این 160 بایت برای ذخیره موقت متغیر ها استفاده کنه 🔸 چرا…
چرا Exploit Dev به Red Zone حساسه؟

اگر روی استک payload میزارید shellcode/ROP ممکنه داخل Red Zone باشه

کامپایلر RSP رو تغییر نداده ولی داده‌ای که تزریق کرد داخل همون محدوده است

پس:

اگر تابع دیگه ای صدا زده بشه داده پاک میشه

اگر interrupt بشه کرش میکنه


چند تا payloadها با stomp شدن Red Zone از کار میوفتن

خیلی از فراخوانی‌ های داخلی libc اولین کاری که میکنن اینه که از Red Zone استفاده بکنن


اگر ROP Chain شما داخل این محدوده باشه overwrite میشه کرش



Stack Alignment
وابسته به Red Zone


اگر اشتباهی فکر کنید فضای زیر RSP امن نیست ممکنه SUB/ADD اشتباه بزنی و استک misalign میشه

Misalignment:

سیستم‌ کال کرش کنه

libc کرش کنه

ROP Chain درست اجرا نشه



مثال عملی

کد C

#include <stdio.h>

void test() {
char *p = (char *)__builtin_frame_address(0);
printf("RSP: %p\n", p);

char buffer[32];
buffer[0] = 'A';
printf("buffer: %p\n", buffer);
}

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


آدرس buffer پایین RSP است

اما RSP کم نشده!

این یعنی buffer داخل Red Zone هست


نکته طلایی:
کامپایلر حتی بدون رزرو استک در Red Zone متغیر میزاره



Why is Exploit Dev sensitive to Red Zone?

If you put the shellcode/ROP payload on the stack, it may be in the Red Zone

The compiler did not change the RSP, but the data it injected is in the same range

So:

If another function is called, the data will be cleared

If it is interrupted, it will crash

Some payloads will fail when the Red Zone is stomped

Many internal libc calls do the first thing they do is use the Red Zone

If your ROP Chain is in this range, it will be overwritten and crash

Stack Alignment

Dependent on the Red Zone

If you mistakenly think that the space below the RSP is not safe, you may make a SUB/ADD mistake and the stack will be misaligned

Misalignment:

System call crashes

libc crashes

ROP Chain does not execute correctly

Practical example

C code

#include <stdio.h>

void test() {
char *p = (char *)__builtin_frame_address(0);

printf("RSP: %p\n", p);

char buffer[32];
buffer[0] = 'A';
printf("buffer: %p\n", buffer);
}

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


The buffer address is below RSP

But RSP is not decreased!

This means the buffer is in the Red Zone

Golden tip:
The compiler places variables in the Red Zone even without stack reservation

@reverseengine
1👎1🔥1
چرا گجت‌ ها یک دفعه کرش میکنن؟

خیلی وقتا ROP Chain رو درست می‌نویسید آفست‌ها هم درسته ولی برنامه بعد از یکی‌ دو گجت کرش میکنه

90 درصد مواقع دلیلش اینه:

دارید ROP رو داخل Red Zone میذارید

یعنی شما فکر میکنی RSP اینجاست ولی داده‌ هایی که تزریق کردید تو 160 بایت پایین‌ تره جایی که اصلا تضمین نشده سالم بمونه



یه تابع داخلی صدا زده می‌شه → Red Zone رو overwrite میکنه → ROP میره هوا

یه interrupt میاد → سیستم‌ عامل اون فضا رو میگیره کرش میکنه

حتی یه printf ساده → Red Zone رو زیر پا میذاره → گجت بعدی اجرا نمیشه


ساده‌ترین نمونه کرش در ROP

برنامه بعد از اجرای اولین گجت روی گجت دوم سیگنال میگیره و از بین میره

چون payload داخل Red Zone بوده و libc اون محدوده رو با داده‌های خودش پر کرده




Why do gadgets crash all at once?

Many times you write the ROP Chain correctly, the offsets are correct, but the program crashes after one or two gadgets

90% of the time the reason is this:

You are putting the ROP in the Red Zone

That is, you think the RSP is here, but the data you injected is 160 bytes below where it is not guaranteed to be intact

An internal function is called → It overwrites the Red Zone → ROP goes to the air

An interrupt comes → The operating system takes that space and crashes

Even a simple printf → It violates the Red Zone → The next gadget does not run

The simplest example of a crash in ROP

After executing the first gadget, the program receives a signal on the second gadget and dies

Because the payload was in the Red Zone and libc filled that area with its own data

@reverseengine
1
خوندن آرگومان‌ ها از استک وقتی زیاد باشن

در x86-64 SysV ABI

رجیستر های آرگومان‌ ها به ترتیب:

1RDI


2 RSI


3 RDX


4 RCX


5 R8


6 R9



اما اگر تعداد آرگومان‌ ها بیشتر از 6 تا بشه بقیه روی استک قرار میگیره




تابع 8 آرگومانی

کد C:

int f(int a, int b, int c, int d, int e, int f, int g, int h) {
return h + a;
}


ارگومان‌ها:

محل آرگومان

a RDI
b RSI
c RDX
d RCX
e R8
f R9
g [rbp+16]
h [rbp+24]


فریم استک:

[rbp+16] → 7th argument
[rbp+24] → 8th argument




اسمبلی:

f:
push rbp
mov rbp, rsp

mov eax, DWORD PTR [rbp+24] ; h
add eax, edi ; + a

pop rbp
ret


یعنی:

h از روی استک خونده میشه

a
در رجیستر edi هست

خروجی در eax


Reading arguments from the stack when there are many

In x86-64 SysV ABI

The argument registers are in order:

1RDI

2 RSI

3 RDX

4 RCX

5 R8

6 R9

But if the number of arguments is more than 6, the rest are placed on the stack

8-argument function

C code:

int f(int a, int b, int c, int d, int e, int f, int g, int h) {

return h + a;

}


Arguments:

Argument location

a RDI
b RSI
c RDX
d RCX
e R8
f R9
g [rbp+16]
h [rbp+24]


Stack frame:

[rbp+16] → 7th argument
[rbp+24] → 8th argument


Assembly:

f:
push rbp
mov rbp, rsp

mov eax, DWORD PTR [rbp+24] ; h
add eax, edi ; + a

pop rbp
ret


That is:

h is read from the stack

a is in the edi register

output in eax

@reverseengine
👍3