0x01 – Basic Linux 32 Assembly

ပထမဦးစြာ assembly ကိုသိထားဖို႕လိုအပ္ပါတယ္။ သို႕ေပမဲ့ အရမ္း ၾကာၾကာေလ့လာေနရင္လည္း လိုရင္းကိုမေရာက္မွာစိုးရိမ္ရပါတယ္။ ေလ့လာခ်င္တာက Exploit Development ဆိုေတာ့ မသိမျဖစ္အေၾကာင္းအရာေတြကို အဓိကထားေလ့လာသြားဖို႕ လိုအပ္ပါတယ္။ ဒါေၾကာင့္ တိုတိုနဲ႕လိုရင္းကိုပဲ အဓိကထားေလ့လာၾကမယ္။

Reference Cheat Sheet

https://www.cheatography.com/siniansung/cheat-sheets/linux-assembler/

General Registers

General Registers မ်ားကို program တစ္ခုမွာ mathematical operations ေတြအတြက္ သံုးၾကတာျဖစ္ပါတယ္။ ဒီထဲမွာမွ

Data , Pointer , Index စသည္ျဖင့္ ထပ္ကြဲပါတယ္။

Data Registers မ်ားမွာ ေအာက္ပါအတိုင္းျဖစ္သည္

EAX -> Primary Accumulator register ျဖစ္ပါတယ္။၄င္းကို input/output နဲ႕ arithmetic instructions ေတြမွာသံုးပါတယ္။

EBX -> Base Register ျဖစ္ပါတယ္။ ၄င္းကို indexed addressing အတြက္သံုးပါတယ္။

ECX -> Count Register ျဖစ္ပါတယ္။ ထပ္ဆင့္ operations ေတြလုပ္ေဆာင္တဲ့အခါမွာ loop count အေနနဲ႕သံုးပါတယ္။

EDX -> Data Register ျဖစ္ပါတယ္။ EAX လိုပဲ input/output မွာသံုးပါတယ္။ EAX နွင့္တြဲျပီး arithmetic instructions ေတြမွာသံုးတာမ်ိဳးလဲရွိပါတယ္။

Pointer Registers မ်ားမွာ ေအာက္ပါအတိုင္းျဖစ္သည္

EIP -> ေနာက္ထပ္ execute လုပ္မယ့္ address ကို ညႊန္းတဲ့ Pointer ျဖစ္ပါတယ္။ (Instructions Pointer)

ESP -> Data ရဲ႕ address ျဖစ္ပါတယ္။ Stack Pointer လို႕ေခၚပါတယ္။

EBP -> Base Pointer ျဖစ္ပါတယ္။ Parameter Value ေတြကို pass လုပ္တဲ့ေနရာမွာ သံုးတာျဖစ္ပါတယ္

Index Registers မ်ားမွာ ေအာက္ပါအတိုင္းျဖစ္သည္

ESI - > String Operations ေတြရဲ႕ Source Index ျဖစ္ပါတယ္။

EDI -> String Operations ေတြရဲ႕ Destination Index ျဖစ္ပါတယ္။

Segment Registers မ်ားမွာ ေအာက္ပါအတိုင္းျဖစ္သည္

ECS -> Code-S­egment
EDS -> Data-S­egment
ESS -> Stack-­Segment
EES -> Extra-­Segment

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

Logical Operations မ်ားမွာ ေအာက္ပါအတိုင္းျဖစ္သည္

neg op -> two-Co­mpl­ement
not op ->invert each bit 
and dest­,s­ource -> dest= dest ^ source
or dest­,s­ource -> dest­=dest  ̬  source
xor dest, surce -> dest = dest XOR source

Instructions မ်ားမွာ ေအာက္ပါအတိုင္းျဖစ္သည္

cmp op1,­op2 -> Compare op1 with op2
test op1,­op2 -> bitwise comparison
jmp dest -> uncond­itional Jump
je dest -> Jump if equal
jne dest -> Jump if not equal
jz dest -> Jump if zero
jnz dest -> Jump if not zero
jg dest -> Jump if greater
jge dest -> Jump if greater or equal
jl dest -> Jump if less
jle dest -> Jump if less or equal

Mnemonic မ်ားမွာ ေအာက္ပါအတိုင္းျဖစ္သည္

mov dest, source -> Moves Data
add dest, value -> Add value to dest
sub dest­,v­alue -> Subtract value3 from dest*
inc dest -> Increment dest
dec dest -> Decrement dest
mul src -> Multiply EAX and src
imul dest, source -> dest = dest * source

Stack Operations မ်ားမွာ ေအာက္ပါအတိုင္းျဖစ္သည္

push source -> Insert Value onto the stack
pop dest -> Remove value from stack

C Program & Assembly

ဒီအေၾကာင္းအရာအား Shellcoder Handbook Second Edition မွ ဥပမာမ်ားႏွင့္ ေကာက္နွုတ္ေဖာ္ျပထားျခင္းျဖစ္ပါသည္။

Example 1

int number;
<code>
number++;

C program တစ္ခုတြင္ integer data type ျဖင့္ number variable တစ္ခုေၾကညာျခင္းျဖစ္ပါသည္။ ထို႕ေနာက္အျခား instructions မ်ားပါဝင္သည္ ကို အတိုခ်ဳပ္ <code> ဟု ေဖာ္ျပထားျခင္းျဖစ္ပါသည္။ ထုိ႕ေနာက္ number အား increment လုပ္မည့္ instruction လာသည္ကို Assembly တြင္ မည္ကဲ့သို႕အလုပ္လုပ္သနည္း။

number dw 0
<code>
mov eax,number
inc eax
mov number,eax

Assign လုပ္သည့္အခ်ိန္တြင္ number ကို define word ျဖင့္ ျပဳလုပ္သည္ ။ value ေၾကညာျခင္းမရွိသျဖင့္ 0 ဟုသတ္မွတ္သည္။ number ကို increment လုပ္သည့္အပိုင္းတြင္ Data Registers ျဖစ္သည့္ eax အား ယူသံုးထားသည္ကိုေတြ႕ရမည္။ mov dest,source ဆိုသည့္ Instructions ကို အထက္ပါစာမ်ားအားဖတ္ထားသည္ဆိုလွ်င္သိပါလိမ့္မည္။ number ထဲမွာ value အား eax သို႕ mov လုပ္မည္ဟုဆိုလိုျခင္းျဖစ္သည္။ move လုပ္သည္ဆိုေပမဲ့ အမွန္တကယ္ေတာ့ copy ကူးျခင္းသာျဖစ္ပါသည္။ number ထဲမွ value သည္ eax ထဲသို႕ကူးေျပာင္းသြားျခင္းမဟုတ္ပါ။ ဥပမာ 0 ဆိုပါစို႕ ။ eax ႏွင့္ number ၏ value မ်ားသည္ လက္ရွိအခ်ိန္တြင္ 0 ျဖစ္ေနၾကသည္ကို သိထားရမည္။

ထို႕ေနာက္ eax အား increment လုပ္သည္။ ျပီးလွ်င္ eax ၏ value ျဖစ္ေနေသာ 1 အား number သို႕ mov ျပန္လုပ္သည္။ ထို႕ေၾကာင့္ လက္ရွိ number သည္ 1 ျဖစ္သြားသည္။

Example 2

int number;
if(number<0)
{
    <code>
}

ဥပမာ ၂ တြင္ က်ေနာ္တို႕ condition ကိုေလ့လာျခင္းျဖစ္သည္။ Assembly တြင္မည္သို႕ျဖစ္မည္ကို နားလည္သည္ဆိုလွ်င္ က်ေနာ္တို႕ ဆက္လက္ေလ့လာဖို႕ အဆင္ေျပသြားပါလိမ့္မည္။

number dw 0
mov eax,number
or eax,eax
jge label
  <no>
label:<yes>

number ထဲမွာ value အား ထံုးစံအတိုင္း eax သို႕ သိမ္းသည္။ ထို႕ေနာက္ eax ႏွင့္ eax ကို or လုပ္ျပီး eax သို႕သိမ္းသည္။ jge label ဆိုသည္မွာ Jump if greater or equal ဟု အထက္တြင္ေဖာ္ျပထားသည္။ ထို႕ေၾကာင့္ 0 ထက္ ၾကီးသည္ သို႕မဟုတ္ 0 ဆိုလွ်င္ yes ရွိသည့္ label မွ instructions မ်ားကိုအလုပ္လုပ္မည္ သို႕မဟုတ္ပါက <no> ရွိသည့္ instructions မ်ားကို အလုပ္လုပ္မည္ဟု ဥပမာေပးထားျခင္းျဖစ္သည္။

ကိုယ္တိုင္စမ္းၾကည့္တာ ပိုျပီး အဆင္ေျပမည္ဟု ယူဆေသာေၾကာင့္ example ေလးေတြကို ထပ္မံစမ္းပါမည္။

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

int main() 
{
	int number=5;
	if(number==5)
		{
			printf("Number is 5\n");
		}
	else
		{
			printf("Number is not 5\n");
		}

return 0;
}

Program ၏ အလုပ္လုပ္ပံုမွာ number သည္ 5 ျဖစ္ခဲ့မည္ဆိုလ်ွင္ 5 ဟု ေျပာမည္ မဟုတ္လွ်င္ မဟုတ္ေၾကာင္းေျပာမည္။

Compile လုပ္ရန္အတြက္ gcc ကို အသံုးျပဳမည္။

gcc -m32 -o if_condition if_condition.c

-m32 သည္ က်ေနာ္႕စက္မွာ 64 bit ျဖစ္ေနေသာေၾကာင့္ 32 bit အေနျဖင့္သာ compile လုပ္ရန္ ေျပာျခင္းျဖစ္သည္။ သင္လည္း အဲ့လိုျဖစ္ေနသည္ဆိုပါက i386 architecture ထည့္သြင္းေပးရန္လိုအပ္ပါသည္။

sudo dpkg --add-architecture i386

architecture ထည့္သြင္းျပီးလ်င္ update လုပ္ေပးရမည္။ ထို႕ေနာက္ header file မ်ားကို ေခၚသံုးရန္အတြက္ library မ်ားလဲ ထည့္သြင္းေပးရမည္။

sudo apt-get update
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386

objdump ကို အသံုးျပဳျပီး disassemble ျပဳလုပ္မည္။

objdump -d if_condition

Disassembled Result

mian function ကိုပဲေဖာ္ျပထားျခင္းျဖစ္ပါသည္။

0804841d <main>:
804841d:	55                   	push   %ebp
804841e:	89 e5                	mov    %esp,%ebp
8048420:	83 e4 f0             	and    $0xfffffff0,%esp
8048423:	83 ec 20             	sub    $0x20,%esp
8048426:	c7 44 24 1c 05 00 00 	movl   $0x5,0x1c(%esp)
804842d:	00 
804842e:	83 7c 24 1c 05       	cmpl   $0x5,0x1c(%esp)
8048433:	75 0e                	jne    8048443 <main+0x26>
8048435:	c7 04 24 f0 84 04 08 	movl   $0x80484f0,(%esp)
804843c:	e8 af fe ff ff       	call   80482f0 <puts@plt>
8048441:	eb 0c                	jmp    804844f <main+0x32>
8048443:	c7 04 24 fc 84 04 08 	movl   $0x80484fc,(%esp)
804844a:	e8 a1 fe ff ff       	call   80482f0 <puts@plt>
804844f:	b8 00 00 00 00       	mov    $0x0,%eax
8048454:	c9                   	leave  
8048455:	c3                   	ret

ပထမ ၅ ေၾကာင္းကို prolog ဟုေခၚပါသည္။ function တစ္ခုစတိုင္း proglog ကအလုပ္လုပ္သည္။ ၄င္းအား stack အေၾကာင္းကိုေလ့လာရာတြင္ အေသးစိတ္ေဖာ္ျပေပးပါမည္။

movl $0x5,0x1c(%esp)

1c သည္ decimal value 28 ျဖစ္သည္။ ဆိုလိုရင္းမွာ 5 အား [esp-28] address တြင္သြားသိမ္းမည္ဟုဆိုလိုပါသည္။ အထက္တြင္ေဖာ္ျပခဲ့သလိုမဟုတ္ပဲ stack ကိုအသံုးျပဳထားတာကိုေတြ႕ရမည္။ stack အေၾကာင္းအား ေနာက္အခန္းမ်ားတြင္မွ အေသးစိတ္ေလ့လာမည္။

က်ေနာ္တို႕ 5 နွင့္ညီမညီစစ္ခဲ့ေသာၾကာင့္ assign လုပ္ထားေသာ varible တန္ဖိုးႏွင့္ 5 ႏွင့္ ညီမညီကို ႏွိုင္းယွဥ္မည္ျဖစ္ေသာေၾကာင့္ cmpl $0x5,0x1c(%esp) ဟုေရးထားသည္ကိုေတြ႕ရမည္။ ထို႕ေနာက္ result အေပၚမူတည္ျပီးဆက္အလုပ္လုပ္ရမွာျဖစ္တယ္

jne 8048443 <main+0x26>

jne သည္ jump if not equal ျဖစ္သည္။ compare လုပ္ရတြင္ မညီဘူးဆိုလ်င္ 8048443 address ရွိရာ instruction သို႕ jump လုပ္မည္ ။ ညီခဲ့မယ္ဆိုလ်ွင္ေတာ့ .plt section ထဲမွ က်ေနာ္တို႕ရဲ႕ string ၅ ျဖစ္ေၾကာင္းေျပာတဲ့ output ကိုထုတ္ျပမည္ျဖစ္သည္။

call 80482f0 <puts@plt>

ျပီးလွ်င္ return 0 ထားခဲ့သည္႕အတြက္ mov 0x0,eax instruction ရွိရာသို႕ jump လုပ္သြားတာကိုေတြ႕ရမည္။

jmp 804844f <main+0x32>

ဒီလိုဆို မညီလ်င္ jump လုပ္သြားမည့္ address တြင္ 5 မဟုတ္ေၾကာင္းျပတဲ့ output ကို လွမ္းေခၚထားတာေတြ႕ရမည္။

call 80482f0 <puts@plt>

ထို႕ေနာက္ EIP value ကို သိမ္းထားေသာ RET ေရာက္လာပါသည္။ Next Instruction Pointer (EIP) ကိုေတြ႕လ်င္ အဲ့ဒီ address ကို ဆက္အလုပ္လုပ္သြားမည္ျဖစ္ပါသည္။

အျခားေသာ Program မ်ားကိုလည္းစမ္းေစခ်င္ပါသည္။ ကိုယ္တိုင္ျမင္ရလွ်င္ပိုျပီးနားလည္မယ္လို႕ထင္ပါတယ္။

 

 

8 Comments

  1. Intel and AT&T Syntax အေျကာင္းေလးကိုပါ ေျပာျပေပးရင္ ပိုေကာင္းမယ္ အကို။ 😀
    Thanks For Sharing Bro 😀

    • ေက်းဇူးတင္ပါတယ္ ညီေလး Intel & AT&T ကလဲ တကယ့္ျပသနာ ဟီး အကိုစဥ္စားထားတာတစ္ခုေတာ့ရွိတယ္ gdb မွာ intel disassembler အေနနဲ႕ပဲ ေနာက္ပိုင္းလုပ္သြားရင္ေကာင္းမလားလို႕ အဲဒါဆို Windows လုပ္ေတာ့လဲ ဆင္သြားေတာ့ သက္သာသြားမလားလို႕ေတြးမိတယ္ ဘယ္လိုသေဘာရလဲ 😀

      • ဟုတ္တယ္ အကို။
        က်ြန္ေတာ္လဲ Intel Syntax ကို ဖတ္ရတာ ပိုသေဘာက်တယ္။
        AT&T Syntax က %() ေတြပါေနလို့ နည္းနည္းရုွပ္တယ္။

        • ဟီး ဒါေပမဲ့ ဒါက Linux ၾကီး AT & T ပဲကစ္တာသဘာဝက်မလားပဲ

  2. ေက်းဇူးပါကိုႀကိီးေရ…
    က်ေနာ္ အဆမ္ဘလီစေလ့လာေနပါပီ…. ??

    • လိုအပ္ခ်က္ေတြ ရွိရင္လဲေျပာပါဦးေနာ္ အကိုလည္းေလ့လာရင္းတစ္ခါတည္းေရးသြားတာမလို႕ပါ 😀

  3. Thz u very much for sharing.Now I’m studying assembly language (version:8085) for pwn.Some syntax are different.btw if we disassembled java program, syntax can be same?

    • Java က သက္သက္ပါ ညီေလး မတူပါဘူး ခုက C program ေတြနဲ႕ပဲျပေနတာပါ Assembly မွာေတာ့ ဘာနဲ႕ပဲေရးေရး assembly ေရာက္ရင္ေတာ့ ဒါေတြပဲရွိလို႕ အလုပ္လုပ္ပံုတူရင္ ဒီလိုပဲ syntax ေတြကျဖစ္မွာပါ Assembly ရရင္ေတာ့ ေကာင္းတာေပါ့ 😀

Comments are closed.