ویرگول
ورودثبت نام
سید عمید قائم مقامی
سید عمید قائم مقامیبرنامه نویسی سیستم ویندوز و مهندسی معکوس و علاقه مند به آموزش.
سید عمید قائم مقامی
سید عمید قائم مقامی
خواندن ۶ دقیقه·۶ روز پیش

زبان اسمبلی قسمت سوم(Shell Code)MessagBox

هدف کلی

این کد یک شلکد (Shellcode) است که:

آدرس GetProcAddress را از حافظه پیدا می‌کند

کتابخانه user32.dll را لود می‌کند

تابع MessageBoxA را پیدا می‌کند

یک پیام "hello" نمایش می‌دهد

سپس برنامه را با ExitProcess خاتمه می‌دهد


بخش اول: پیدا کردن بیس آدرس kernel32.dll

.386 ; هدف: پردازنده 386 (32 بیتی) .model flat, stdcall ; مدل حافظه flat و قرارداد فراخوانی stdcall .code start:

xor ecx, ecx

رجیستر ECX را صفر می‌کند (معادل mov ecx, 0 اما سریع‌تر)


ASSUME fs:NOTHING mov eax, dword ptr fs:[ecx+30h] ASSUME fs:ERROR

از سگمنت FS آدرس PEB (Process Environment Block) را می‌خواند

آفست 0x30 در TEB (Thread Environment Block) اشاره به PEB دارد

چون ECX=0 است، fs:[ecx+30h] == fs:[30h]


TEB └─ [0x30] ──► PEB

mov eax, dword ptr ds:[eax+0Ch]

از PEB آفست 0x0C را می‌خواند که به PEB_LDR_DATA اشاره دارد


PEB └─ [0x0C] ──► PEB_LDR_DATA

mov esi, dword ptr ds:[eax+14h]

از PEB_LDR_DATA آفست 0x14 را می‌خواند که InMemoryOrderModuleList است

این لیست شامل ماژول‌های لود شده در حافظه است

PEB_LDR_DATA └─ [0x14] ──► InMemoryOrderModuleList ├─ [0] ntdll.dll ├─ [1] kernel32.dll ◄── هدف ما └─ ...

بخش دوم: پیمایش لیست ماژول‌ها

lodsd ; eax = dword ptr ds:[esi] ; ESI به طور خودکار +4 می‌شود

اولین عنصر لیست را می‌خواند (ntdll.dll را رد می‌کند) LODSD = Load String Double word


xchg eax, esi

مقدار EAX و ESI را جابجا می‌کند حالا ESI به اولین ورودی واقعی اشاره دارد.


lodsd ; eax = dword ptr ds:[esi]

دومین عنصر لیست را می‌خواند (kernel32.dll)


mov ebx, dword ptr ds:[eax+10h]

آفست 0x10 از ورودی ماژول = بیس آدرس kernel32.dll

حالا EBX = بیس آدرس kernel32.dll


بخش سوم: پیدا کردن Export Table

mov edx, dword ptr ds:[ebx+3Ch]

از بیس آدرس، آفست 0x3C را می‌خواند

این آفست به PE Header (امضای NT) اشاره دارد


add edx, ebx

آدرس واقعی PE Header = بیس + آفست


mov edx, dword ptr ds:[edx+78h]

آفست 0x78 در PE Header = آفست Export Table


add edx, ebx

آدرس واقعی Export Table = بیس + آفست

PE Header └─ [0x78] ──► Export Table ├─ [0x20] ──► AddressOfNames ├─ [0x24] ──► AddressOfNameOrdinals └─ [0x1C] ──► AddressOfFunctions

mov esi, dword ptr ds:[edx+20h] add esi, ebx

آدرس AddressOfNames را می‌خواند (جدول نام توابع)


xor ecx, ecx

شمارنده حلقه را صفر می‌کند.


بخش چهارم: جستجوی GetProcAddress

jne_01: inc ecx

شمارنده را یک واحد افزایش می‌دهد (برای پیدا کردن اوردینال)


lodsd ; eax = dword ptr ds:[esi]

آفست نام تابع بعدی را می‌خواند


add eax, ebx

آدرس واقعی نام تابع = بیس + آفست


cmp dword ptr ds:[eax], 50746547h

بررسی می‌کند آیا ۴ بایت اول = "GetP" است؟

50746547h به صورت Little Endian = "GetP"


jne jne_01

اگر برابر نبود به اول حلقه برمی‌گردد


cmp dword ptr ds:[eax+04h], 41636F72h

بررسی می‌کند آیا بایت‌های بعدی = "rocA" است؟


jne jne_01
cmp dword ptr ds:[eax+08h], 65726464h

بررسی می‌کند آیا بایت‌های بعدی = "ddre" است؟


"GetP" + "rocA" + "ddre" = "GetProcAddre..." یعنی تابع GetProcAddress پیدا شد!
jne jne_01

بخش پنجم: گرفتن آدرس واقعی تابع

mov esi, dword ptr ds:[edx+24h] add esi, ebx

آدرس AddressOfNameOrdinals (جدول اوردینال‌ها)


mov cx, word ptr ds:[esi+ecx*2h]

اوردینال تابع GetProcAddress را از جدول می‌خواند


dec ecx

اوردینال را یک واحد کم می‌کند (به دلیل اینکه inc در ابتدای حلقه اضافه شده بود)


mov esi, dword ptr ds:[edx+1Ch] add esi, ebx

آدرس AddressOfFunctions (جدول آدرس توابع)


mov edx, dword ptr ds:[esi+ecx*4h] add edx, ebx

آدرس واقعی تابع GetProcAddress را محاسبه می‌کند

حالا EDX = آدرس GetProcAddress


بخش ششم: فراخوانی LoadLibraryA

xor ecx, ecx push ebx ; بیس آدرس kernel32.dll push edx ; آدرس GetProcAddress push ecx ; صفر (null terminator) push 41797261h ; "Ayra" ◄─┐ push 7262694Ch ; "rbiL" ◄─┤ روی هم = "LoadLibraryA\0" push 64616F4Ch ; "daoL" ◄─┘ push esp ; اشاره‌گر به رشته "LoadLibraryA" push ebx ; هندل kernel32.dll call edx ; GetProcAddress(kernel32, "LoadLibraryA")

بعد از فراخوانی، EAX = آدرس LoadLibraryA


add esp, 0Ch

پاکسازی پارامترها از stack (رشته "LoadLibraryA")


pop ecx

مقدار null را از stack برمی‌دارد


بخش هفتم: لود کردن user32.dll

push eax ; آدرس LoadLibraryA را ذخیره می‌کند xor eax, eax mov ax, 6C6Ch ; "ll" push eax ; "ll\0\0" push 642E3233h ; "d.23" push 72657375h ; "resu" push esp ; اشاره‌گر به "user32.dll\0" call dword ptr ss:[esp+10h] ; LoadLibraryA("user32.dll")

رشته روی stack: "user" + "32.d" + "ll\0" = "user32.dll"

بعد از فراخوانی، EAX = هندل user32.dll


add esp, 0Ch

پاکسازی رشته از stack


بخش هشتم: پیدا کردن MessageBoxA

push eax ; هندل user32.dll xor eax, eax mov eax, 2341786Fh ; "23Axo" (با null جعلی) push eax sub dword ptr ss:[esp+3h], 23h ; تبدیل '23' به null push 42656761h ; "Bega" -> "egaB" push 7373654Dh ; "sseM" push esp ; اشاره‌گر به "MessageBox" push dword ptr ss:[esp+10h] ; هندل user32.dll call dword ptr ss:[esp+1Ch] ; GetProcAddress(user32, "MessageBoxA")

رشته ساخته شده: "MesS" + "ageB" + "ox\0" = "MessageBoxA"


add esp, 0Ch

پاکسازی رشته از stack

push eax ; آدرس MessageBoxA xor eax, eax mov eax, 23737365h ; با null جعلی push eax sub dword ptr ss:[esp+03h], 23h ; اصلاح null push 636F7250h ; "corP" push 74697845h ; "tixE" push esp ; اشاره‌گر به "ExitProcess" push dword ptr ss:[esp+20h] ; هندل kernel32.dll call dword ptr ss:[esp+20h] ; GetProcAddress(kernel32, "ExitProcess")

بخش دهم: نمایش MessageBox

push eax ; آدرس ExitProcess xor eax, eax mov eax, 236E6977h ; "win" با null جعلی push eax sub dword ptr ss:[esp+03h], 23h ; اصلاح null push esp ; اشاره‌گر به "win\0" (caption) xor eax, eax mov al, 6Fh ; 'o' push eax ; "o\0" push 6C6C6568h ; "lleh" push esp ; اشاره‌گر به "hello\0" (متن پیام) xor eax, eax push eax ; NULL (هندل پنجره) push dword ptr ss:[esp+04h] ; "hello" push dword ptr ss:[esp+14h] ; "win" (caption) xor eax, eax push eax ; MB_OK = 0 call dword ptr ss:[esp+28h] ; MessageBoxA(NULL, "hello", "win", 0)

بخش یازدهم: خاتمه برنامه

add esp, 14h

پاکسازی stack



.386 .model flat, stdcall .code start: xor ecx,ecx ASSUME fs:NOTHING mov eax,dword ptr fs:[ecx+30h] ASSUME fs:ERROR mov eax,dword ptr ds:[eax+0Ch] mov esi,dword ptr ds:[eax+14h] lodsd; eax,dword ptr ds:[esi] xchg eax,esi lodsd; eax,dword ptr ds:[esi] mov ebx,dword ptr ds:[eax+10h] mov edx,dword ptr ds:[ebx+3Ch] add edx,ebx mov edx,dword ptr ds:[edx+78h] add edx,ebx mov esi,dword ptr ds:[edx+20h] add esi,ebx xor ecx,ecx jne_01: inc ecx lodsd; eax,dword ptr ds:[esi] add eax,ebx cmp dword ptr ds:[eax],50746547h jne jne_01 cmp dword ptr ds:[eax+04h],41636F72h jne jne_01 cmp dword ptr ds:[eax+08h],65726464h jne jne_01 mov esi,dword ptr ds:[edx+24h] add esi,ebx mov cx,word ptr ds:[esi+ecx*2h] dec ecx mov esi,dword ptr ds:[edx+1Ch] add esi,ebx mov edx,dword ptr ds:[esi+ecx*4h] add edx,ebx xor ecx,ecx push ebx push edx push ecx push 41797261h push 7262694Ch push 64616F4Ch push esp push ebx call edx add esp,0Ch pop ecx push eax xor eax,eax mov ax,6C6Ch push eax push 642E3233h push 72657375h push esp call dword ptr ss:[esp+10h] add esp,0Ch push eax xor eax,eax mov eax,2341786Fh push eax sub dword ptr ss:[esp+3h],23h push 42656761h push 7373654Dh push esp push dword ptr ss:[esp+10h] call dword ptr ss:[esp+1Ch] add esp,0Ch push eax xor eax,eax mov eax,23737365h push eax sub dword ptr ss:[esp+03h],23h push 636F7250h push 74697845h push esp push dword ptr ss:[esp+20h] call dword ptr ss:[esp+20h] add esp,0Ch push eax xor eax,eax mov eax,236E6977h push eax sub dword ptr ss:[esp+03h],23h push esp xor eax,eax mov al,6Fh push eax push 6C6C6568h push esp xor eax,eax push eax push dword ptr ss:[esp+04h] push dword ptr ss:[esp+14h] xor eax,eax push eax call dword ptr ss:[esp+28h] add esp,14h END start

Telegram: @CaKeegan
Bale: @CaKeegan
Gmail : amidgm2020@gmail.com

Assemblywindows
۳
۰
سید عمید قائم مقامی
سید عمید قائم مقامی
برنامه نویسی سیستم ویندوز و مهندسی معکوس و علاقه مند به آموزش.
شاید از این پست‌ها خوشتان بیاید