0x03 – Understanding Memory Layout

Exploit Development ကို ေလ့လာတဲ့အခါမွာ Stack Overflow တို႕ Heap Overflow စသည့္ အားနည္းခ်က္တို႕က အဓိက အခန္းမွာပါဝင္ေနတာေတြ႕ရပါလိမ့္မယ္။ ဒီေတာ့ က်ေနာ္တို႕ အေနနဲ႕ Linux 32 ရဲ႕ Memory အေၾကာင္းကို ပထမဆံုးနားလည္ထားတာက ေလ့လာရာမွာ ပိုျပီးလြယ္ကူေစမွာျဖစ္ပါတယ္။ ဒါမွသာ အမွန္တကယ္ေလ့လာတဲ့အခါက်ရင္ အဆင္ေျပမယ္လို႕ က်ေနာ္စာေမးေနက် အကိုတစ္ေယာက္ကေျပာပါတယ္။ ဒီေတာ့ ေလ့လာၾကတာေပါ့။  Reference Link ကိုေတာ့ ေအာက္ဆံုးမွာထည့္ေပးထားပါတယ္။

Memory Layout က ဘယ္လိုမ်ိုးရွိလဲ

User Stack
    |
    v
Memory Mapped Region for Shared Libraries or Anything Else
    ^
    |
Heap
Uninitialised Data (.bss)
Initialised Data (.data)
Program Text (.text)
0

Stack ကို Local Variables ေတြအတြက္သံုးတယ္လို႕ အရင္ အခန္းေတြတုန္းကက်ေနာ္ေျပာခဲ့ပါတယ္။ heap ကို ေတာ့ Stack မွာ ထည့္လို႕အဆင္မေျပတဲ့ အရာေတြ သို႕မဟုတ္ size ကို ၾကိဳတင္ခန္႕မွန္းလို႕မရတဲ့ေနရာေတြမွာသံုးတယ္လို႕ သိရပါတယ္။ .bss တို႕ .data တို႕ .text တို႕ကိုေတာ့ အေရွ႕ခန္းေတြမွာ ေသခ်ာေျပာျပျပီးျပီျဖစ္ပါတယ္။

ဒါေပမဲ့ Tool ေတြ ေၾကာင့္ရလာတဲ့ result အရ lower address ကို အေပၚမွာထားတာေၾကာင့္ Layout ကို ေအာက္ကလိုမ်ိဳး ထားလိုက္ရင္ မ်က္လံုးထဲပိုျပီး ျမင္ပါလိမ့္မယ္

-Lower Address
0
Program Text (.text)
Initialised Data (.data)
Uninitialised Data (.bss)
Heap
    |
    v
Memory Mapped Region for Shared Libraries or Anything Else
    ^
    |
User Stack
-Higher Address

ဒီလိုဆို C program ကေနပဲ memory မွာ ဘယ္လိုအလုပ္လုပ္တယ္ဆိုတာကိုေလ့လာၾကာတေပါ့။

Global Variables ေတြဟာ .data နဲ႕ .bss ကို သြားတယ္ဆိုတာေတာ့သိျပီးသားျဖစ္လို႕ မေျပာေတာ့ပါဘူး ။

Stack နဲ႕ Heap ကိုပဲနားလည္ေအာင္ ေလ့လာၾကမယ္။

Stack

Stack မွာ function ေတြနဲ႕ local variables ေတြကိုသိမ္းတယ္လို႕သိထားတယ္။ ဟုတ္ျပီ ဘယ္လိုမ်ိုးသံုးတာလဲ?

int main() 
{
int a=10;
}

ရိုးရိုးေလးပဲေရးလိုက္မယ္။ stack မွာ သြားသိမ္းတယ္ဆိုတဲ့ function ရယ္ local variable ပဲပါတယ္။ ဒီလိုဆို compile လုပ္ျပီး disassemble လုပ္ၾကည့္ရေအာင္။

function တစ္ခုစတိုင္းမွာ အေပၚက instructions ၃ ေၾကာင္းကအျမဲတမ္းအလုပ္လုပ္တာေတြကရလိမ့္မယ္။ function ကို stack မွာသိမ္းတယ္လို႕ေျပာခဲ့တယ္ေနာ္။ အဲဒီေတာ့ function တစ္ခုစလိုက္ျပီးဆိုတာနဲ႕ push ebp ဆိုတဲ့ instruction နဲ႕ stack မွာ ebp ကို ထားလိုက္တယ္။ စစခ်င္းမွာ ebp ထဲမွာ 0x0 ပဲရွိေနလိမ့္မယ္။ esp ကိုေတာ့ value ၁၀၀ လို႕က်ေနာ္တို႕ အလြယ္မွတ္ထားလိုက္မယ္။

$ebp = 0x0
$esp =  0x100

push ebp ဆိုေတာ့ 0x0 ကို stack ထဲသြားထည့္လိုက္မယ္။

Stack 
esp = 0x100
ebp = 0x0

mov esp,ebp ဆိုတဲ့ instruction ကိုေရာက္ေတာ့ esp value ကုိ ebp ထဲကိုသြားထည့္လိုက္တယ္။ ဒီေတာ့ stack မွာ

Stack 
esp=0x100
ebp=0x100

ေနာက္ေတာ့ ဘာလုပ္လဲဆိုေတာ့ sub 0x10,esp တဲ့ ဆိုလိုတာက esp ကို 0x10=16(dec) နွုတ္ျပီးရင္ esp ထဲျပန္ထည့္ခဲ့မယ္တဲ့ ဒီေတာ့

Stack 
esp = 0x84
ebp = 0x100

ဒါဆိုရင္ esp နဲ႕ ebp ၾကားမွာ 16 bytes စာေနရာရွိတယ္လို႕သိရတယ္။ ေနာက္တစ္ခုက ebp ျပီးလွ်င္ RET ရွိတယ္လို႕သိထားရမယ္။ ဒီ function ကိုလုပ္ျပီးရင္ ေနာက္ထပ္ဆက္လုပ္မယ္ EIP (next instruction pointer) ကို သိမ္းထားတာျဖစ္တယ္။ ဒါကိုေတာ့ ေနာက္တစ္ခန္း မွာ ေသခ်ာေလးေရးေပးမယ္။ ေနာက္ instruction တစ္ခုကိုဆက္ၾကည့္မယ္။ movl 0xa,-0x4($ebp)  လို႕ဆိုတယ္။ ဘာလုပ္မွာလဲဆိုရင္ ebp-4 ေနရာမွာ 0xa=10(dec) ကိုသြားထည့္မယ္လို႕ေျပာတယ္။ ဟုတ္တယ္ေလ က်ေနာ္တို႕ int a ကို 10 ထည့္ခဲ့တာကိုး။ ဒီေတာ့

Stack 
esp = 0x84
ebp -4 (0x96) -> 0xa
ebp = 0x100

ဒီလိုဆို local variable ေတြ function ေတြ stack မွာ ဘယ္လုိထားတယ္ဆိုတာကိုနားလည္ျပီလို႕ထင္ပါတယ္။ ခုနေရးထားတဲ့ program ကို ျပန္ၾကည့္မယ္။ ခုက မ်က္စိထဲျမင္ေအာင္ တမင္ ၁၀၀ လို႕သတ္မွတ္ျပီးစဥ္းစားတာျဖစ္တယ္။

gdb ကိုသံုးျပီးေတာ့ က်ေနာ္တို႕ ၾကည့္လို႕ရပါတယ္။

gdb -q stack_test

ျပီးရင္ run command နဲ႕ run လိုက္မယ္။  program မထြက္သြားဖို႕အတြက္ က်ေနာ္ leave ဆိုတဲ့ instruction မွာ break ခဏလုပ္တယ္။ မဟုတ္ရင္ထြက္သြားရင္ stack ထဲမွာ ဘာမွရွိေတာ့မွာ မဟုတ္လို႕ပါ။

break *0x080483ed

run မယ္

instruction တစ္ခုခ်င္းအလုပ္လုပ္သြားခ်င္ရင္ stepi ကိုသံုးလို႕ရတယ္ ni = next instruction ကိုလဲသံုးလို႕ရတယ္။ ျပီးရင္ တစ္ခုလုပ္ျပီးတိုင္း registers ကို ျပန္ၾကည့္ဖို႕အတြက္ i r (info registers) ကိုသံုးလို႕ရတယ္။ ဒီေတာ့ sub 0x10,$esp မွာ ဘာျဖစ္သြားလဲၾကည့္ၾကည့္မယ္။

10 ထည့္ေတာ့ေရာ

esp နဲ႕ ebp ၾကားမွာ ၁၆ bytes ရွိတယ္ ebp-4 ေနရာမွာ 0xa ကိုသြားထည့္တယ္ဆိုတာ က်ေနာ္တို႕ေတြ႕ရမွာျဖစ္ပါတယ္။ ဒီေလာက္ဆို stack ရဲ႕ အလုပ္လုပ္ပံုကို နားလည္ျပီလို႕ ယူဆပါတယ္။ စမ္းေစခ်င္ပါတယ္။ က်ေနာ္လဲ ဖတ္လိုက္စမ္းလိုက္နဲ႕ပါပဲ ။ example ၾကည့္လိုက္ ကိုယ့္ဘာကိုေရးျပီး ျပန္ၾကည့္လိုက္လုပ္ပါတယ္။ လုပ္ၾကည့္ေစခ်င္ပါတယ္။

Heap

Heap က်ေတာ့ stack လိုမဟုတ္ေတာ့ဘူး heap ကို သံုးတယ္ဆိုတာကိုက stack မွာ ရွိတာထက္မ်ားတယ္ဆိုရင္ heap ကို သံုးတာျဖစ္တယ္။ dynamic memory ျဖစ္တာေၾကာင့္ stack မွာ သိမ္းလို႕မဆန္႕တဲ့ဟာေတြအတြက္ heap ကို သံုးတယ္လို႕သိရပါတယ္။ ဒီေတာ့ heap ကိုေရာ ဘယ္လိုအလုပ္လုပ္သလဲ ဆိုတာ သိေအာင္ ေလ့လာၾကည့္ၾကမယ္။

Heap
dynamic memories

Example ေလးနဲ႕ပဲ ေလ့လာတာေပါ့။

int main() 
{
int a=10;
int *p;
p=(int*)malloc(sizeof(int));
*p=10;
}

int *p ဆိုျပီး က်ေနာ္တို႕ pointer အမ်ိဳးအစားတစ္ခုေၾကညာလိုက္တယ္ ဘာလို႕လဲဆိုရင္ int a=10 လိုမ်ိဳးေၾကညာလိုက္မယ္ဆိုရင္ stack ထဲမွာပဲသိမ္းမွာေလ။ ခုက heap မွာသိမ္းခ်င္တာျဖစ္တယ္ ။ heap ကို သံုးမယ္ဆိုေတာ့ malloc() function လိုလာတယ္ malloc() က heap မွာ memory allocation လုပ္ေပးတယ္ ၊ argument အေနနဲ႕ size ဘယ္ေလာက္ဆိုတာေတာ့လိုတယ္။ ခုက sizeof(int) လို႕ေျပာထားေတာ့ integer တစ္လံုးစာပဲေပါ့။ မသိရင္ထုတ္ၾကည့္လိုက္ 4 ရမယ္။ ဒီလုိလုပ္လိုက္ျပီဆိုတာနဲ႕ heap မွာ 4 bytes အေနနဲ႕ allocate လုပ္တယ္။ pointer ကေတာ့ stack မွာပဲေပါ့ ။ ဒီေတာ့ မ်က္လံုးထဲျမင္ေအာင္ေျပာမယ္ဆိုရင္

-Stack            -Heap
main()             [allocation for p] 4 bytes
a=10
p

ဒီလိုဆို *p=10 ဆိုေတာ့ heap ထဲမွာ 10 ကိုသြားသိမ္းတယ္ p က အစတည္းက heap ထဲက address ကို point လုပ္ျပီးသားေလ။ ဘယ္လိုျဖစ္သြားမလဲ

-Stack            -Heap
main()             [allocation for p] 4 bytes = 10
a=10
p

heap ကိုၾကည့္ဖို႕အတြက္ example program ေလးနဲ႕ပဲစမ္းၾကည့္တာေပါ့။ ဒါေပမဲ့ program ကို ခဏတန္႕ထားဖို႕လိုပါတယ္ ။ မဟုတ္ရင္ exit ျဖစ္ျဖစ္သြားမွာမဟုတ္လား။ ဒါေၾကာင့္ user input ေစာင့္ေနေအာင္ getchar(); ေလးေနာက္ဆံုးမွာ ထည့္လိုက္မယ္။

int main() 
{
int a=10;
int *p;
p=(int*)malloc(sizeof(int));
*p=10;
getchar();
}

ဒီလိုဆို input ကိုေစာင့္ေနတုန္း memory ကိုၾကည့္လို႕ရတာေပါ့။

./heap_test ကို run လိုက္မယ္ ျပီးရင္ heap_test run ေနတဲ့ process id ကိုၾကည့္ခ်င္ေတာ့ ps -aux | grep heap_test ဆိုျပီး ေရြးၾကည့္လိုက္မယ္။

process id သိျပီဆိုရင္ေတာ့ ဒီ process က run ေနတဲ့ memory ကိုက်ေနာ္တို႕ၾကည့္လို႕ရပါတယ္။

strace နဲ႕ system call ေတြကိုၾကည့္မယ္ဆိုရင္ေတာ့ 4 bytes ေနနရာယူသြားတာကအစျမင္ရမွာျဖစ္ပါတယ္။ malloc() function ကို သံုးတာနဲက mmap() နဲ႕ brk() system call ေတြကို ေခၚသံုးတာျဖစ္တဲ့အတြက္ေၾကာင့္ mmap မွာ က်ေနာ္တို႕ၾကည့္လို႕ရပါတယ္။ Ref 

strace ./heap_test

ဒီေလာက္ဆို memory layout ကို နားလည္ျပီလို႕ ယူဆလိုက္ပါတယ္။ ေနာက္ပိုင္းအခန္းေတြေလ့လာရင္း ပိုနားလည္လာလိမ့္မယ္လို႕ေတာ့ က်ေနာ္ထင္ပါတယ္။ အမ်ားၾကီးလုပ္ရဦးမွာဆိုေတာ့ေလ

Reference

https://gist.github.com/CMCDragonkai/10ab53654b2aa6ce55c11cfc5b2432a4
Google
tutorial point