[L2H] – Debugging with gdb – Part 2

Part 1 ကေတာ့ ဒီမွာျပန္ဖတ္လို႕ရပါတယ္။ Part 1 မွာ gdb ကိုသံုးတာေလာက္ေတာ့ေကာင္းေကာင္းသိသြားျပီလို႕ယူဆပါတယ္။ Local Vairables ေတြနဲ႕ Stack ရဲ႕ ပံုစံကိုလဲ debug လုပ္ခဲ့ၾကတယ္။ ဒီေတာ့ Part 2 မွာေတာ့ ဒီထက္ပိုျပီး စိတ္ဝင္စားစရာေကာင္းတာေလးေတြကို စျပီးေလ့လာၾကတာေပါ့ 😀

Function Call

Function call ေတြ ကို Debug လုပ္ၾကည့္မယ္။ ဒီေတာ့ Function အနည္းဆံုး ၂ခုပါတဲ့ Program ေလးကိုစလုပ္မယ္။

Add function

#include <stdio.h>
int add(int a,int b)
{
        return a=a+b;
}
int main()
{
        int result;
        result=add(2,3);
        printf("Retruned from add() =%d\n",result);
}

function ၂ ခုထည့္ထားတယ္။ main function ကေန add function ကို ေခၚမယ္ ။ argument အေနနဲ႕ 2,3 ဆိုျပီး က်ေနာ္တို႕ထည့္ထားတယ္။ ဒီေနရာမွာက်ေနာ္တို႕ ဘာေတြ debug လုပ္ျပီး သင္ယူနိုင္မလဲ? အၾကမ္းအားျဖင့္ function ၁ ခုစီမွာ Stack frame တစ္ခုစီယူသြားတာကိုက်ေနာ္တို႕ေတြ႕ရမယ္။ main function ကေန add function ကို ေခၚျပီးတဲ့အခ်ိန္မွာ Main ကိုျပန္လာျပီးေတာ့ print လုပ္ရဦးမယ္။ ဒီေတာ့ ျပန္လာရမယ့္ address ကိုဘယ္မွာသိမ္းမွာလဲ ? ေနာက္တစ္ခုက argument ၂ ခုကိုေရာ ဘယ္လိုသိမ္းျပီး ဘယ္လို add function ကိုသြားေခၚသလဲ ။ ဒါေတြကို Debugging လုပ္ျပီး က်ေနာ္တို႕ မ်က္ေစ့နဲ႕ ကိုယ္တိုင္ျမင္နိုင္မယ္။

Function ေတြကို disassemble အရင္လုပ္လိုက္မယ္။ဒါက part1 မွာတည္းကေျပာျပီးသားေတြျဖစ္ပါတယ္။

Stack Frame

Add function disassbly

(gdb) disas add
Dump of assembler code for function add:
   0x0804840b <+0>:     push   ebp
   0x0804840c <+1>:     mov    ebp,esp
   0x0804840e <+3>:     mov    eax,DWORD PTR [ebp+0xc]
   0x08048411 <+6>:     add    DWORD PTR [ebp+0x8],eax
   0x08048414 <+9>:     mov    eax,DWORD PTR [ebp+0x8]
   0x08048417 <+12>:    pop    ebp
   0x08048418 <+13>:    ret
End of assembler dump.

Main function disassembly

(gdb) disas main
Dump of assembler code for function main:
   0x08048419 <+0>:     lea    ecx,[esp+0x4]
   0x0804841d <+4>:     and    esp,0xfffffff0
   0x08048420 <+7>:     push   DWORD PTR [ecx-0x4]
   0x08048423 <+10>:    push   ebp
   0x08048424 <+11>:    mov    ebp,esp
   0x08048426 <+13>:    push   ecx
   0x08048427 <+14>:    sub    esp,0x14
   0x0804842a <+17>:    push   0x3
   0x0804842c <+19>:    push   0x2
   0x0804842e <+21>:    call   0x804840b <add>
   0x08048433 <+26>:    add    esp,0x8
   0x08048436 <+29>:    mov    DWORD PTR [ebp-0xc],eax
   0x08048439 <+32>:    sub    esp,0x8
   0x0804843c <+35>:    push   DWORD PTR [ebp-0xc]
   0x0804843f <+38>:    push   0x80484e0
   0x08048444 <+43>:    call   0x80482e0 <printf@plt>
   0x08048449 <+48>:    add    esp,0x10
   0x0804844c <+51>:    mov    eax,0x0
   0x08048451 <+56>:    mov    ecx,DWORD PTR [ebp-0x4]
   0x08048454 <+59>:    leave
   0x08048455 <+60>:    lea    esp,[ecx-0x4]
   0x08048458 <+63>:    ret
End of assembler dump.

Function တစ္ခုက Stack frame တစ္ခုစီရွိတယ္လို႕ေျပာတယ္။ ဒီေတာ့ main ကိုအရင္ၾကည့္မယ္

push ebp မွာ က်ေနာ္ breakpoint ထားလုိက္မယ္။

(gdb) break *main+10
Breakpoint 2 at 0x8048423

ဒါကိုအလုပ္လုပ္တဲ့အခ်ိန္မွာ က်ေနာ္တို႕က Stack frame ဘယ္လုိယူသြားလဲျမင္ခ်င္တာျဖစ္တဲ့အတြက္ gdb မွာ instruction တစ္ခု run တိုင္း Stack ကို ၾကည့္ဖို႕လိုတယ္။ ဒါေၾကာင့္ stop လုပ္တိုင္းမွာ stack ကို ျပဖို႕အတြက္ hook-stop ေလးတစ္ခု define လုပ္ေပးမယ္။

(gdb) define hook-stop
Type commands for definition of "hook-stop".
End with a line saying just "end".
>x/32wx $esp
>end

ဒီေတာ့ တစ္ခါ run တိုင္း သူကလာျပမယ္။

(gdb) run
Starting program: /root/GDB/function
0xffffd65c:     0xf7e31637      0xf7fc9000      0xf7fc9000      0x00000000
0xffffd66c:     0xf7e31637      0x00000001      0xffffd704      0xffffd70c
0xffffd67c:     0x00000000      0x00000000      0x00000000      0xf7fc9000
0xffffd68c:     0xf7ffdc04      0xf7ffd000      0x00000000      0xf7fc9000
0xffffd69c:     0xf7fc9000      0x00000000      0xff8291bd      0xc6059fad
0xffffd6ac:     0x00000000      0x00000000      0x00000000      0x00000001
0xffffd6bc:     0x08048310      0x00000000      0xf7feeff0      0xf7fe9880
0xffffd6cc:     0xf7ffd000      0x00000001      0x08048310      0x00000000

Breakpoint 2, 0x08048423 in main ()

push ebp မွာရပ္ထားခဲ့တယ္။ ဒီေတာ့ သိပ္အဆင္မေျပေသးဘူး ။ Next Instruction ေတြဘာေတြပါလာျပမွာပိုအဆင္ေျပမယ္။

(gdb) define hook-stop
Redefine command "hook-stop"? (y or n) y
Type commands for definition of "hook-stop".
End with a line saying just "end".
>x/32wx $esp
>x/2i $eip
>x $ebp
>end

ျပန္ run ၾကည့္မယ္။

(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/GDB/function
0xffffd65c:     0xf7e31637      0xf7fc9000      0xf7fc9000      0x00000000
0xffffd66c:     0xf7e31637      0x00000001      0xffffd704      0xffffd70c
0xffffd67c:     0x00000000      0x00000000      0x00000000      0xf7fc9000
0xffffd68c:     0xf7ffdc04      0xf7ffd000      0x00000000      0xf7fc9000
0xffffd69c:     0xf7fc9000      0x00000000      0x7d39e954      0x44bee744
0xffffd6ac:     0x00000000      0x00000000      0x00000000      0x00000001
0xffffd6bc:     0x08048310      0x00000000      0xf7feeff0      0xf7fe9880
0xffffd6cc:     0xf7ffd000      0x00000001      0x08048310      0x00000000
=> 0x8048423 <main+10>: push   ebp
   0x8048424 <main+11>: mov    ebp,esp
   0x0: Error while running hook_stop:
Cannot access memory at address 0x0

Breakpoint 2, 0x08048423 in main ()

အဆင္ေျပသြားျပီ break ထားတာက push ebp မွာဆိုတာလဲ ျမင္ရျပီ $ebp က မရွိေသးေတာ့ 0x0 ျဖစ္ေနတာေတြ႕ရမယ္။ stack frame က အခုမွေဆာက္မွာကိုး $ebp က ဘာမွမရွိေသးဘူး ။ $esp ကေတာ့သိတယ္ 0xffffd65c ေပါ့။ ဟုတ္ျပီဗ်ာ။ Instruction တစ္ေၾကာင္းခ်င္း run မယ္။

push ebp -> ebp ကို Stack ထဲထည့္မယ္။ push သည္ stack ထဲကိုထည့္တာျဖစ္တယ္။

(gdb) ni
0xffffd658:     0x00000000      0xf7e31637      0xf7fc9000      0xf7fc9000
0xffffd668:     0x00000000      0xf7e31637      0x00000001      0xffffd704
0xffffd678:     0xffffd70c      0x00000000      0x00000000      0x00000000
0xffffd688:     0xf7fc9000      0xf7ffdc04      0xf7ffd000      0x00000000
0xffffd698:     0xf7fc9000      0xf7fc9000      0x00000000      0x7d39e954
0xffffd6a8:     0x44bee744      0x00000000      0x00000000      0x00000000
0xffffd6b8:     0x00000001      0x08048310      0x00000000      0xf7feeff0
0xffffd6c8:     0xf7fe9880      0xf7ffd000      0x00000001      0x08048310
=> 0x8048424 <main+11>: mov    ebp,esp
   0x8048426 <main+13>: push   ecx
   0x0: Error while running hook_stop:
Cannot access memory at address 0x0
0x08048424 in main ()

0x0000000 သည္ stack ရဲ႕ ထိပ္ဆံုးကိုေရာက္လာျပီ ။ အေပၚ result မွာ blod နဲ႕ italic လုပ္ျပထားပါတယ္။

ေနာက္ထပ္ instruction က mov ebp,esp -> esp ကို ebp ဆီ move လုပ္မယ္။ဒီေတာ့လက္ရွိ ebp ကဘာလဲ esp ကဘာလဲ တစ္ခ်က္ၾကည့္ထားလိုက္မယ္။

(gdb) x $esp
   0xffffd658:  add    BYTE PTR [eax],al
(gdb) x $ebp
   0x0: Cannot access memory at address 0x0

ebp က မထူေသးဘူး ။ esp က 658 ျဖစ္တယ္။ အိုေက move ခိုင္းလိုက္ေတာ့မယ္။

(gdb) ni
0xffffd658:     0x00000000      0xf7e31637      0xf7fc9000      0xf7fc9000
0xffffd668:     0x00000000      0xf7e31637      0x00000001      0xffffd704
0xffffd678:     0xffffd70c      0x00000000      0x00000000      0x00000000
0xffffd688:     0xf7fc9000      0xf7ffdc04      0xf7ffd000      0x00000000
0xffffd698:     0xf7fc9000      0xf7fc9000      0x00000000      0x7d39e954
0xffffd6a8:     0x44bee744      0x00000000      0x00000000      0x00000000
0xffffd6b8:     0x00000001      0x08048310      0x00000000      0xf7feeff0
0xffffd6c8:     0xf7fe9880      0xf7ffd000      0x00000001      0x08048310
=> 0x8048426 <main+13>: push   ecx
   0x8048427 <main+14>: sub    esp,0x14
   0xffffd658:  add    BYTE PTR [eax],al
0x08048426 in main ()

ebp ေလး 658 ျဖစ္သြားျပီ ။ အမွန္က အေပၚမွာလဲ hook-stop မွာတည္းကထုတ္ထားျပီးသား။ ေသခ်ာခ်င္ရင္ ဒီလိုၾကည့္မယ္။

(gdb) x $ebp
   0xffffd658:  add    BYTE PTR [eax],al

esp က ဟာ ebp ကိုေရာက္သြားျပီ။ ေနာက္ထပ္ Instruction ကေတာ့ push ecx ျဖစ္တယ္။ ေလာေလာဆယ္ ecx ကဘာလဲ ? stack ထဲကိုထည့္ေတာ့မွာဆိုေတာ့ ၾကည့္လိုက္မယ္။

(gdb) x $ecx
   0xffffd670:  add    DWORD PTR [eax],eax

670 လို႕ပဲအလြယ္မွတ္လိုက္မယ္။ run ၾကည့္မယ္။

(gdb) ni
0xffffd654:     0xffffd670      0x00000000      0xf7e31637      0xf7fc9000
0xffffd664:     0xf7fc9000      0x00000000      0xf7e31637      0x00000001
0xffffd674:     0xffffd704      0xffffd70c      0x00000000      0x00000000
0xffffd684:     0x00000000      0xf7fc9000      0xf7ffdc04      0xf7ffd000
0xffffd694:     0x00000000      0xf7fc9000      0xf7fc9000      0x00000000
0xffffd6a4:     0x7d39e954      0x44bee744      0x00000000      0x00000000
0xffffd6b4:     0x00000000      0x00000001      0x08048310      0x00000000
0xffffd6c4:     0xf7feeff0      0xf7fe9880      0xf7ffd000      0x00000001
=> 0x8048427 <main+14>: sub    esp,0x14
   0x804842a <main+17>: push   0x3
   0xffffd658:  add    BYTE PTR [eax],al
0x08048427 in main ()

ecx stack ထဲေရာက္သြားျပီ ။ Bold and italic လုပ္ျပထားပါတယ္။

esp က ခုဆိုရင္ 654 ျဖစ္သြားျပီ။

(gdb) x $esp
   0xffffd654:  jo     0xffffd62c

ေနာက္ထပ္ instuction ကေတာ့ esp ထဲကေန 0x14 ကို နွုတ္မယ္တဲ့ ။ Decimail တန္ဖိုးကေတာ့ 20 ေပါ့။

ဒါဆို ရင္ၾကည့္ၾကည့္လိုက္တာေပါ့ ။

0xffffd654 – 0x14 ကို calculator နဲ႕တြက္လိုက္မယ္။

ဒါဆိုရင္ အခု instruction ကိုေရာက္တဲ့အခါ esp ဟာ 640 ျဖစ္သြားမယ္။

(gdb) ni
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x08048481
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x7d39e954      0x44bee744      0x00000000
0xffffd6b0:     0x00000000      0x00000000      0x00000001      0x08048310
=> 0x804842a <main+17>: push   0x3
   0x804842c <main+19>: push   0x2
   0xffffd658:  add    BYTE PTR [eax],al
0x0804842a in main ()
(gdb) x $esp
   0xffffd640:  add    DWORD PTR [eax],eax

Ok ! နားလည္ျပီ ။ အဲ့မွာ main ရဲ႕ stack frame ကိုေဆာက္လို႕ျပီးသြားပါျပီ။ ဟုတ္လား ဘယ္လိုတုန္း ။ ပံုေလးနဲ႕ျပမယ္ဗ်ာ

အနီနဲ႕ျပထားတဲ့ အဝန္းအဝိုင္းေလး ကေတာ့ main function ရဲ႕ stack frame ေပါ့ ။

အစိမ္းနဲ႕ျပထားတာေလးေတြကေတာ့ stack ရဲ႕ pointer esp နဲ႕ base pointer ebp တို႕ျဖစ္တယ္။

640 – ESP

658 – EBP

push တစ္ခုလုပ္တိုင္း esp address က ငယ္ငယ္လာတယ္။ ေနာက္တစ္ခုက တစ္ဖက္ပိတ္ၾကီးလဲျဖစ္တယ္။

ခုေန pop လုပ္ရင္ ဘာထြက္လာမလဲ? stack ရဲ႕ အေပၚဆံုးက value ေတြထြက္လာျဖစ္တယ္ ။

Local Variable

Stack frame ထဲမွာ local variable ေတြဘယ္လိုသိမ္းလဲ ? အခု program မွာ က result က local variable ျဖစ္တယ္။ 2 နဲ႕ 3 ကေတာ့ add function အတြက္ argument ေတြျဖစ္တယ္။

အခုအလုပ္လုပ္မွာ ဘာ instruction လဲ ?

(gdb)
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x08048481
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
0xffffd6b0:     0x00000000      0x00000000      0x00000001      0x08048310
=> 0x804842a <main+17>: push   0x3
   0x804842c <main+19>: push   0x2
   0xffffd658:  add    BYTE PTR [eax],al
0x0804842a in main ()

pus 0x3 တဲ့ ေနာက္တစ္ခုက 0x2 ဒီေတာ့ add function ရဲ႕ argument ေတြကို stack ထဲအရင္ push မယ္ေပါ့။ ok ၂ ခုလံုး run လိုက္ေတာ့မယ္။

(gdb) ni
0xffffd63c:     0x00000003      0x00000001      0xffffd704      0xffffd70c
0xffffd64c:     0x08048481      0xf7fc93dc      0xffffd670      0x00000000
0xffffd65c:     0xf7e31637      0xf7fc9000      0xf7fc9000      0x00000000
0xffffd66c:     0xf7e31637      0x00000001      0xffffd704      0xffffd70c
0xffffd67c:     0x00000000      0x00000000      0x00000000      0xf7fc9000
0xffffd68c:     0xf7ffdc04      0xf7ffd000      0x00000000      0xf7fc9000
0xffffd69c:     0xf7fc9000      0x00000000      0x73741faf      0x4af311bf
0xffffd6ac:     0x00000000      0x00000000      0x00000000      0x00000001
=> 0x804842c <main+19>: push   0x2
   0x804842e <main+21>: call   0x804840b <add>
   0xffffd658:  add    BYTE PTR [eax],al
0x0804842c in main ()
(gdb)
0xffffd638:     0x00000002      0x00000003      0x00000001      0xffffd704
0xffffd648:     0xffffd70c      0x08048481      0xf7fc93dc      0xffffd670
0xffffd658:     0x00000000      0xf7e31637      0xf7fc9000      0xf7fc9000
0xffffd668:     0x00000000      0xf7e31637      0x00000001      0xffffd704
0xffffd678:     0xffffd70c      0x00000000      0x00000000      0x00000000
0xffffd688:     0xf7fc9000      0xf7ffdc04      0xf7ffd000      0x00000000
0xffffd698:     0xf7fc9000      0xf7fc9000      0x00000000      0x73741faf
0xffffd6a8:     0x4af311bf      0x00000000      0x00000000      0x00000000
=> 0x804842e <main+21>: call   0x804840b <add>
   0x8048433 <main+26>: add    esp,0x8
   0xffffd658:  add    BYTE PTR [eax],al
0x0804842e in main ()

3 နဲ႕ 2 ကေတာ့ stack ရဲ႕ထိပ္ဆံုးမွာ ေနရာယူထားျပီ ။ ESP လဲ ထံုးစံအတိုင္းထပ္ငယ္သြားျပီ။

ျပီးရင္လုပ္မဲ့ instruction က call add() တဲ့ ။ ဟာ ဒါဆိုရင္ add function ကိုေခၚျပီေပါ့။ ဒါဆိုရင္ သြား break ထားမွျဖစ္မယ္ မဟုတ္ရင္ အဲ့ကျပန္လာမွ ဆိုမျဖစ္ေသးဘူး ။ ဒီမွာတစ္ခ်က္ၾကည့္မယ္ဆိုရင္ function call ကိုေခၚေနျပီျဖစ္တယ္။ argument ေတြက ျမင္တဲ့အတိုင္းပဲ argument 1 ကို stack ရဲ႕ထိပ္ဆံုးမွာထားထားတယ္။ argument 2 ကေတာ့ သူ႕ျပီးေနာက္တစ္ခုေပါ့ ။ က်ေနာ္တို႕ခုဆိုရင္ argument ေတြဟာ stack ရဲ႕ ထိပ္ဆံုးကဟာကို ယူတယ္ဆိုတာ မ်က္ေစ့နဲ႕ျမင္္လိုက္ရျပီျဖစ္ပါတယ္။

ok break မယ္ add function မွာ

(gdb) break *add+0
Breakpoint 3 at 0x804840b

ဆက္ run မယ္ဆိုရင္ add function ကိုေရာက္ရေတာ့မွာျဖစ္တယ္။

(gdb) ni
0xffffd634:     0x08048433      0x00000002      0x00000003      0x00000001
0xffffd644:     0xffffd704      0xffffd70c      0x08048481      0xf7fc93dc
0xffffd654:     0xffffd670      0x00000000      0xf7e31637      0xf7fc9000
0xffffd664:     0xf7fc9000      0x00000000      0xf7e31637      0x00000001
0xffffd674:     0xffffd704      0xffffd70c      0x00000000      0x00000000
0xffffd684:     0x00000000      0xf7fc9000      0xf7ffdc04      0xf7ffd000
0xffffd694:     0x00000000      0xf7fc9000      0xf7fc9000      0x00000000
0xffffd6a4:     0x73741faf      0x4af311bf      0x00000000      0x00000000
=> 0x804840b <add>:     push   ebp
   0x804840c <add+1>:   mov    ebp,esp
   0xffffd658:  add    BYTE PTR [eax],al

Breakpoint 3, 0x0804840b in add ()

Break သြားျပီ ။ အခုလုပ္မယ့္ Instruction က push ebp တဲ့ ။ က်ေနာ္တို႕သိသြားျပီ သူ stack frame ေဆာက္ဦးမွာမဟုတ္လား ?

ဒီလိုဆို အေပၚက reuslt မွာ Blod / italic ျပထားတဲ့ address က ဘာေလးလဲ ?

=> 0x804842e <main+21>: call 0x804840b <add> 
0x8048433 <main+26>: add esp,0x8

add function ကိုေခၚတဲ့ instruction ျပီးရင္ main ကိုျပန္လာရမွာမဟုတ္လား။ အဲ့ေတာ့ add function ကေနျပန္တဲ့အခါက်ရင္ ဆက္အလုပ္လုပ္မယ့္ Instruction ကို Stack ထဲမွာသြားသိမ္းထားတယ္ ဆိုတာ က်ေနာ္တို႕ျမင္လိုက္ရျပန္ျပီ။

ဒီေတာ့ add function ကိုလဲ တစ္ဆင့္ခ်င္းလုပ္သြားခိုင္းလိုက္မယ္။ push ebp ေပါ့

(gdb) ni
0xffffd630:     0xffffd658      0x08048433      0x00000002      0x00000003
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x08048481
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
=> 0x804840c <add+1>:   mov    ebp,esp
   0x804840e <add+3>:   mov    eax,DWORD PTR [ebp+0xc]
   0xffffd658:  add    BYTE PTR [eax],al
0x0804840c in add ()

ဒီတစ္ခါ bold ထားတာေလးကေတာ့ saved ebp လို႕ေခၚပါတယ္။ main function ရဲ႕ ebp ကို save လိုက္တာပါလား။ ဟုတ္ျပီး mov ebp,esp ကိုဆက္လုပ္ခိုင္းမယ္။

(gdb) ni
0xffffd630:     0xffffd658      0x08048433      0x00000002      0x00000003
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x08048481
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
=> 0x804840e <add+3>:   mov    eax,DWORD PTR [ebp+0xc]
   0x8048411 <add+6>:   add    DWORD PTR [ebp+0x8],eax
   0xffffd630:  pop    eax
0x0804840e in add ()

ebp နဲ႕ esp တူသြားျပီ။ ေနာက္တစ္ခုကဘာလဲ ? mov eax , DWORD PTR [ebp+0xc] ျဖစ္တယ္။

[ebp+0xc] ဆိုတဲ့ address မွာရွိတဲ့ value ကို eax ထဲထည့္မယ္တဲ့ ။ အဲဒီ address ကဘယ္ေလာက္လဲ

calculator မသံုးေတာ့ပဲနဲ႕ gdb ကိုပဲသံုးရင္ပိုမေကာင္းဘူးလား

(gdb) print $ebp+0xc
$1 = (void *) 0xffffd63c

အဲ့ဒါကို ဘာလို႕ eax ထဲထည့္ေနတာလဲ ဘာတန္ဖိုးရွိလို႕လဲ

(gdb) x/x 0xffffd63c
0xffffd63c:     0x00000003

ေၾသာ္ … 3 ရွိေနတာကိုး ။ ဟုတ္ျပီဗ် ။ 3 ကို eax ထဲထည့္မယ္ေပါ့ ။ ထည့္ေစဗ်ား

(gdb) ni
0xffffd630:     0xffffd658      0x08048433      0x00000002      0x00000003
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x08048481
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
=> 0x8048411 <add+6>:   add    DWORD PTR [ebp+0x8],eax
   0x8048414 <add+9>:   mov    eax,DWORD PTR [ebp+0x8]
   0xffffd630:  pop    eax
0x08048411 in add ()
(gdb) print $eax
$2 = 3

EAX ကို arithmetic operations ေတြလုပ္တဲ့အခါ သံုးတယ္ ။ ဒါေၾကာင့္ handle လုပ္ဖို႕သံုးတယ္ဆိုတာ ခုဆိုရင္ ျမင္လိုက္ရျပန္တယ္။ ေနာက္ထပ္ instruction က ေတာ့ add DWORD PTR [ebp+0x8],eax ပါ ။

eax နဲ႕ [ebp+0x8] ကို ေပါင္းမယ္တဲ့ ။ ကဲ ၾကည့္တာေပါ့ ။ [ebp+0x8] မွာဘာရွိမလဲ

(gdb) x/x $ebp+0x8
0xffffd638:     0x00000002

2 တဲ့ ။ eax ထဲမွာက 3 ရွိတယ္ ။ 2 နဲ႕ 3 နဲ႕ေပါင္းမယ္ေပါ့ ။ မိုက္ခ်က္ပဲ

ေပါင္းခိုင္းလိုက္မယ္။ ေနဦး ေမးစရာရွိတယ္ result ကဘယ္မွာျပန္ထားမွာလဲ?

(gdb) ni
0xffffd630:     0xffffd658      0x08048433      0x00000005      0x00000003
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x08048481
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
=> 0x8048414 <add+9>:   mov    eax,DWORD PTR [ebp+0x8]
   0x8048417 <add+12>:  pop    ebp
   0xffffd630:  pop    eax
0x08048414 in add ()

Result ကို Destination မွာပဲထားတာဆိုတာ အေျဖရသြားမယ္။ (Bold ျပထားပါတယ္ )

ျပီးေတာ့ အဲဒါကို eax ထဲျပန္ထည့္ဦးမယ္။ ေနာက္ instuction က အဲဒါျဖစ္တယ္။ ဘာလို႕ eax ထဲကိုျပန္ထည့္ေနရတာလဲ ?

(gdb) ni
0xffffd630:     0xffffd658      0x08048433      0x00000005      0x00000003
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x08048481
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
=> 0x8048417 <add+12>:  pop    ebp
   0x8048418 <add+13>:  ret
   0xffffd630:  pop    eax
0x08048417 in add ()
(gdb) x/x $eax
0x5:    Cannot access memory at address 0x5

eax ထဲကို 5 ေရာက္သြားျပီ ။ ထားပါေတာ့ ဘာေၾကာင့္ဆိုတာျပီးရင္ၾကည့္တာေပါ့ ။ အခုလုပ္မွာက pop ebp တဲ့ ။

ebp ထဲကို stack ရဲ႕အေပၚဆံုးက value ကို ထည့္ေတာ့မယ္ေပါ့ ။ ဘာလို႕လဲ ?

0xffffd658

အရမ္းမိုက္တယ္ဗ်ာ ။ saved ebp ေလ stack ရဲ႕ အေပၚဆံုးမွာ အရင္ main function ရဲ႕ ebp ကို saved ထားတာအေၾကာင္းမဲ့ သက္သက္မဟုတ္ဘူးပဲ ။

(gdb) ni
0xffffd634:     0x08048433      0x00000005      0x00000003      0x00000001
0xffffd644:     0xffffd704      0xffffd70c      0x08048481      0xf7fc93dc
0xffffd654:     0xffffd670      0x00000000      0xf7e31637      0xf7fc9000
0xffffd664:     0xf7fc9000      0x00000000      0xf7e31637      0x00000001
0xffffd674:     0xffffd704      0xffffd70c      0x00000000      0x00000000
0xffffd684:     0x00000000      0xf7fc9000      0xf7ffdc04      0xf7ffd000
0xffffd694:     0x00000000      0xf7fc9000      0xf7fc9000      0x00000000
0xffffd6a4:     0x73741faf      0x4af311bf      0x00000000      0x00000000
=> 0x8048418 <add+13>:  ret
   0x8048419 <main>:    lea    ecx,[esp+0x4]
   0xffffd658:  add    BYTE PTR [eax],al
0x08048418 in add ()

ျပီးရင္ဘာဆက္လုပ္မွာလဲဗ်ာ ။ ret တဲ့ ။ ret သည္ stack ရဲ႕ အေပၚဆံုးက value ကို Next Instruction Pointer အေနနဲ႕ယူမယ့္ Instruction ျဖစ္တယ္။ ဒီေတာ့ EIP ဟာ stack ရဲ႕အေပၚဆံုးကဟာဆိုေတာ့

0x08048433

Wow ! ဒါ main က မွတ္လာတဲ့ instruction ပဲ add function ကို ေခၚျပီးရင္ ျပန္လုပ္ရမယ့္ဟာ။ ျမင္ျပီထင္တယ္။ heeh 😀 ကဲျပန္ပါေစဦး

(gdb) ni
0xffffd638:     0x00000005      0x00000003      0x00000001      0xffffd704
0xffffd648:     0xffffd70c      0x08048481      0xf7fc93dc      0xffffd670
0xffffd658:     0x00000000      0xf7e31637      0xf7fc9000      0xf7fc9000
0xffffd668:     0x00000000      0xf7e31637      0x00000001      0xffffd704
0xffffd678:     0xffffd70c      0x00000000      0x00000000      0x00000000
0xffffd688:     0xf7fc9000      0xf7ffdc04      0xf7ffd000      0x00000000
0xffffd698:     0xf7fc9000      0xf7fc9000      0x00000000      0x73741faf
0xffffd6a8:     0x4af311bf      0x00000000      0x00000000      0x00000000
=> 0x8048433 <main+26>: add    esp,0x8
   0x8048436 <main+29>: mov    DWORD PTR [ebp-0xc],eax
   0xffffd658:  add    BYTE PTR [eax],al
0x08048433 in main ()

ျပန္သြားျပီ ။ ဘယ္ေလာက္လွလိုက္လဲဗ်ာ ။ ျပန္လဲေရာက္ေရာ ခုန Add function က တည္ေဆာက္ခဲ့တဲ့ stack frame ၾကီးက မရွိေတာ့ဘူးဗ် ။ ဘာမွမလုပ္ထားတဲ့အတိုင္း ျပန္ျဖစ္သြားျပီမဟုတ္လား ။ ထူးျခားတာဆိုလို႕တစ္ခုေလးပဲရွိတယ္။ eax ထဲမွာေတာ့ 5 ပါလာတယ္။ အဲဒါ return ျပန္ထားလို႕ေပါ့ ။

ေနပါဦး ။ ေသခ်ာၾကည့္ၾကည့္မယ္ဆိုရင္ stack ရဲ႕ထိပ္ဆံုးမွာလဲ 5 ပါလာတယ္ဗ် ။ ေနာက္လုပ္မယ့္ဟာေလးၾကည့္ျပီး နားလည္လိုက္ရေအာင္ဗ်ာ။ add esp,0x8 တဲ့ esp ကို ေပါင္းျပန္ျပီ ။ ဒါကဘာလုပ္ခ်င္ျပန္တာလဲ ?

0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x08048481
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
0xffffd6b0:     0x00000000      0x00000000      0x00000001      0x08048310
=> 0x8048436 <main+29>: mov    DWORD PTR [ebp-0xc],eax
   0x8048439 <main+32>: sub    esp,0x8
   0xffffd658:  add    BYTE PTR [eax],al
0x08048436 in main ()

ခုနက 3 တို႕ 5 တို႕က်န္ေနတာေလးကိုရွင္းပစ္လိုက္တာဟ ။ Stack ထဲမွာ မရွိေတာ့ဘူး ။ ညဏ္မ်ားလြန္းတယ္ဗ်ာ။ ေနာက္တစ္ခုကိုၾကည့္ရေအာင္ ၊ [ebp-0xc] ထဲကို eax ကိုထည့္မယ္တဲ့ 5 ကို သြားထည့္မွာေပါ့။ ဘယ္နားထည့္မွာလဲ

(gdb) x/x $ebp-0xc
0xffffd64c:     0x08048481

ဟုတ္ျပီ ထည့္ခိုင္းလိုက္မယ္။

(gdb) ni
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x00000005
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
0xffffd6b0:     0x00000000      0x00000000      0x00000001      0x08048310
=> 0x8048439 <main+32>: sub    esp,0x8
   0x804843c <main+35>: push   DWORD PTR [ebp-0xc]
   0xffffd658:  add    BYTE PTR [eax],al
0x08048439 in main ()

ဟုတ္တယ္ဗ် ။ ထည့္လိုက္ျပီ ။ ေနာက္တစ္ခုက esp ကို 0x8 ျပန္နွုတ္ျပန္တယ္။

(gdb) ni
0xffffd638:     0x00000005      0x00000003      0x00000001      0xffffd704
0xffffd648:     0xffffd70c      0x00000005      0xf7fc93dc      0xffffd670
0xffffd658:     0x00000000      0xf7e31637      0xf7fc9000      0xf7fc9000
0xffffd668:     0x00000000      0xf7e31637      0x00000001      0xffffd704
0xffffd678:     0xffffd70c      0x00000000      0x00000000      0x00000000
0xffffd688:     0xf7fc9000      0xf7ffdc04      0xf7ffd000      0x00000000
0xffffd698:     0xf7fc9000      0xf7fc9000      0x00000000      0x73741faf
0xffffd6a8:     0x4af311bf      0x00000000      0x00000000      0x00000000
=> 0x804843c <main+35>: push   DWORD PTR [ebp-0xc]
   0x804843f <main+38>: push   0x80484e0
   0xffffd658:  add    BYTE PTR [eax],al
0x0804843c in main ()

ေဟာ ဟို ၂ ခုျပန္ပါလာျပန္တယ္။ ဘာလုပ္ခ်င္ေနတာလဲ မသိဘူးေနာ္။ ေနာက္တစ္ခုကေတာ့ စိတ္ဝင္စားစရာပဲ ။

push DWORD PTR [ebp-0xc] ဆိုတာ ebp-0xc ထဲက 5 ကို stack ရဲ႕ ထိပ္ဆံုးကိုပို႕တာေပါ့ ။

(gdb) ni
0xffffd634:     0x00000005      0x00000005      0x00000003      0x00000001
0xffffd644:     0xffffd704      0xffffd70c      0x00000005      0xf7fc93dc
0xffffd654:     0xffffd670      0x00000000      0xf7e31637      0xf7fc9000
0xffffd664:     0xf7fc9000      0x00000000      0xf7e31637      0x00000001
0xffffd674:     0xffffd704      0xffffd70c      0x00000000      0x00000000
0xffffd684:     0x00000000      0xf7fc9000      0xf7ffdc04      0xf7ffd000
0xffffd694:     0x00000000      0xf7fc9000      0xf7fc9000      0x00000000
0xffffd6a4:     0x73741faf      0x4af311bf      0x00000000      0x00000000
=> 0x804843f <main+38>: push   0x80484e0
   0x8048444 <main+43>: call   0x80482e0 <printf@plt>
   0xffffd658:  add    BYTE PTR [eax],al
0x0804843f in main ()

ေနာက္တစ္ခုက ဘာၾကီးတုန္းဗ်ာ ။ push 0x80484e0 တဲ့ ။ ဘယ္ကဟာၾကီးကို stack ထဲပို႕ေနတာလဲ ? အဲဒါဘာၾကီးလဲ ?

(gdb) info proc mappings
process 8520
Mapped address spaces:

        Start Addr   End Addr       Size     Offset objfile
         0x8048000  0x8049000     0x1000        0x0 /root/GDB/function
         0x8049000  0x804a000     0x1000        0x0 /root/GDB/function
         0x804a000  0x804b000     0x1000     0x1000 /root/GDB/function
        0xf7e18000 0xf7e19000     0x1000        0x0
        0xf7e19000 0xf7fc6000   0x1ad000        0x0 /lib32/libc-2.23.so
        0xf7fc6000 0xf7fc7000     0x1000   0x1ad000 /lib32/libc-2.23.so
        0xf7fc7000 0xf7fc9000     0x2000   0x1ad000 /lib32/libc-2.23.so
        0xf7fc9000 0xf7fca000     0x1000   0x1af000 /lib32/libc-2.23.so
        0xf7fca000 0xf7fcd000     0x3000        0x0
        0xf7fd5000 0xf7fd6000     0x1000        0x0
        0xf7fd6000 0xf7fd9000     0x3000        0x0 [vvar]
        0xf7fd9000 0xf7fda000     0x1000        0x0 [vdso]
        0xf7fda000 0xf7ffc000    0x22000        0x0 /lib32/ld-2.23.so
        0xf7ffc000 0xf7ffd000     0x1000    0x22000 /lib32/ld-2.23.so
        0xf7ffd000 0xf7ffe000     0x1000    0x23000 /lib32/ld-2.23.so
        0xfffdd000 0xffffe000    0x21000        0x0 [stack]

process ကို ၾကည့္တဲ့ command နဲ႕ၾကည့္လိုက္မယ္ဆိုရင္ အေပၚဆံုးက bold ျပထားတဲ့ထဲကပဲ။ ဒီထဲမွာဘာပါလို႕ stack ထဲပို႕ေနရတာလဲ? ၾကည့္မယ္ကြာ

(gdb) ni
0xffffd630:     0x080484e0      0x00000005      0x00000005      0x00000003
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x00000005
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
=> 0x8048444 <main+43>: call   0x80482e0 <printf@plt>
   0x8048449 <main+48>: add    esp,0x10
   0xffffd658:  add    BYTE PTR [eax],al
0x08048444 in main ()

ဘာေတြပါလဲ ၾကည့္ဦးမွပါ

(gdb) x/s 0x080484e0
0x80484e0:      "Retruned from add() =%d"

Wow ! ဒါတို႕ရဲ႕ string ပဲ ။ တို႕ေတြ printf လုပ္ခဲ့တဲ့ဟာ ။ သေဘာေပါက္ခဲ့ျပီ ။ ဒါဆုိေနာက္တစ္ခုကလြယ္သြားျပီ printf ကိုလွမ္းေခၚတာေပါ့ ။

argument က ဒါဆို stack ရဲ႕ အေပၚဆံုးကဟာကိုယူတာေပါ့ ။ ျမင္ျပီလားမသိဘူးဗ် ။ ဆက္ run လိုက္မယ္။

(gdb) ni
0xffffd630:     0x080484e0      0x00000005      0x00000005      0x00000003
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x00000005
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
=> 0x8048449 <main+48>: add    esp,0x10
   0x804844c <main+51>: mov    eax,0x0
   0xffffd658:  add    BYTE PTR [eax],al
0x08048449 in main ()

Stack ထဲမွာေတာ့ အရင္တိုင္းပဲရွိေနတုန္းပဲ ။ exp ကို 0x10 ေပါင္းမယ့္ကိစၥကခုမွလာမွာဗ်

(gdb) ni
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x00000005
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
0xffffd6b0:     0x00000000      0x00000000      0x00000001      0x08048310
=> 0x804844c <main+51>: mov    eax,0x0
   0x8048451 <main+56>: mov    ecx,DWORD PTR [ebp-0x4]
   0xffffd658:  add    BYTE PTR [eax],al
0x0804844c in main ()

ဟာ! ခုနက ဟာေတြဘာတစ္ခုမွမရွိေတာ့ပါလား။ eax ကိုလဲ 0x0 ထည့္ဦးမယ္တဲ့ဗ်ာ ။

(gdb) ni
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x00000005
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
0xffffd6b0:     0x00000000      0x00000000      0x00000001      0x08048310
=> 0x8048451 <main+56>: mov    ecx,DWORD PTR [ebp-0x4]
   0x8048454 <main+59>: leave
   0xffffd658:  add    BYTE PTR [eax],al
0x08048451 in main ()
(gdb) x/x $eax
0x0:    Cannot access memory at address 0x0

eax လဲ 0 ျဖစ္သြားျပီ။

ecx ထဲကိုက်ေတာ့ ebp-0x4 တဲ့

(gdb) ni
0xffffd640:     0x00000001      0xffffd704      0xffffd70c      0x00000005
0xffffd650:     0xf7fc93dc      0xffffd670      0x00000000      0xf7e31637
0xffffd660:     0xf7fc9000      0xf7fc9000      0x00000000      0xf7e31637
0xffffd670:     0x00000001      0xffffd704      0xffffd70c      0x00000000
0xffffd680:     0x00000000      0x00000000      0xf7fc9000      0xf7ffdc04
0xffffd690:     0xf7ffd000      0x00000000      0xf7fc9000      0xf7fc9000
0xffffd6a0:     0x00000000      0x73741faf      0x4af311bf      0x00000000
0xffffd6b0:     0x00000000      0x00000000      0x00000001      0x08048310
=> 0x8048454 <main+59>: leave
   0x8048455 <main+60>: lea    esp,[ecx-0x4]
   0xffffd658:  add    BYTE PTR [eax],al
0x08048454 in main ()
(gdb) x/x $ebp-0x4
0xffffd654:     0xffffd670
(gdb) x/x $ecx
0xffffd670:     0x00000001

push လုပ္ထားတဲံ ecx ေလးပဲ ၊ သူ႕ေနရာသူျပန္သြားထားတာေပါ့ ။ မိုက္ျပီ leave မယ္တဲ့ ။ leave ကေရာ ဘာလုပ္တာလဲ ? ( ref )

Stack frame ကို ေဆာက္ေတာ့ push ebp ဘာညာကေန စေဆာက္သြားတာကိုေတြ႕ခဲ့ရတယ္။ အဲ့မွာ esp က ebp ျဖစ္သြားျပီးေတာ့ ebp အေဟာင္းကိုေတာ့ save ထားခဲ့လိုက္တယ္ေလ ။ leave ကဘာလဲဆိုရင္ ေတာ့ အဲဒီဟာကိုေျပာင္းျပန္ျပန္လုပ္တာပဲျဖစ္တယ္။ ebp ရဲ႕ address ဟာ esp address ျပန္ ျဖစ္သြားျပီးေတာ့ ၊ ebp ကေတာ့ saved EBP အေဟာင္းေလးပဲျပန္ထားခဲ့မယ္ဆိုတဲ့ အလုပ္ကိုလုပ္တာျဖစ္တယ္။ ဒီေတာ့ ဘာမွမလုပ္ခဲ့သလိုေပါ့ ။ ဟန္ေဆာင္ေကာင္းလိုက္တာ ။ အဲဒါေၾကာင့္ break မလုပ္ပဲ run လို႕ program exit ျဖစ္သြားတဲ့အခ်ိန္ ဘာ stack မွာမရွိေတာ့ဘူးေလ ။ ျမင္ျပီထင္တယ္ ။ က်ေနာ္ေတာ့ျမင္တယ္ဗ် ဟီး 😀

(gdb) ni
0xffffd65c:     0xf7e31637      0xf7fc9000      0xf7fc9000      0x00000000
0xffffd66c:     0xf7e31637      0x00000001      0xffffd704      0xffffd70c
0xffffd67c:     0x00000000      0x00000000      0x00000000      0xf7fc9000
0xffffd68c:     0xf7ffdc04      0xf7ffd000      0x00000000      0xf7fc9000
0xffffd69c:     0xf7fc9000      0x00000000      0x73741faf      0x4af311bf
0xffffd6ac:     0x00000000      0x00000000      0x00000000      0x00000001
0xffffd6bc:     0x08048310      0x00000000      0xf7feeff0      0xf7fe9880
0xffffd6cc:     0xf7ffd000      0x00000001      0x08048310      0x00000000
=> 0x8048455 <main+60>: lea    esp,[ecx-0x4]
   0x8048458 <main+63>: ret
   0x0: Error while running hook_stop:
Cannot access memory at address 0x0
0x08048455 in main ()

မထြက္ေသးဘူးဟ lea exp,[ecx-0x4] တဲ့ ။ ဘာလုပ္ဦးမို႕လဲမသိဘူး ။ စပ္စုမယ္ေလ မထူးေတာ့ဘူး

(gdb) x/x $ecx-0x4
0xffffd66c:     0xf7e31637

ecx ထဲမွာ ခုနက ဘာထည့္ထားေသးလဲမွတ္မိလား ? သူ႕ နဂိုဟာကိုပဲ ျပန္ထုတ္ထားတာေလ ။ အဲ့ထဲကဟာကို lea

load effetive address လုပ္ဦးမယ္ဆိုေတာ့ ဘာေၾကာင့္လဲဗ်ာ။

LEA ကို အေပၚမွာတည္းကလုပ္ခဲ့တာ ။ က်ေနာ္တို႕ main function မွာ stack frame စတဲ့ေနရာကစၾကည့္လို႕မသိလိုက္တာျဖစ္တယ္။

(gdb) disas main
Dump of assembler code for function main:
   0x08048419 <+0>:     lea    ecx,[esp+0x4]
   0x0804841d <+4>:     and    esp,0xfffffff0
   0x08048420 <+7>:     push   DWORD PTR [ecx-0x4]

ဘာေၾကာင့္လဲဆိုရင္ေတာ့ x86 assembly ေတြဟာ C တို႕ pascal တို႕လို High Level Language ေတြကို Array ေတြ သံုးတဲ့အခါ အဆင္ေျပေအာင္လို႕ Design ခ်ထားလို႕ျဖစ္တယ္ ။ ( read more )

(gdb) ni
0xffffd66c:     0xf7e31637      0x00000001      0xffffd704      0xffffd70c
0xffffd67c:     0x00000000      0x00000000      0x00000000      0xf7fc9000
0xffffd68c:     0xf7ffdc04      0xf7ffd000      0x00000000      0xf7fc9000
0xffffd69c:     0xf7fc9000      0x00000000      0x73741faf      0x4af311bf
0xffffd6ac:     0x00000000      0x00000000      0x00000000      0x00000001
0xffffd6bc:     0x08048310      0x00000000      0xf7feeff0      0xf7fe9880
0xffffd6cc:     0xf7ffd000      0x00000001      0x08048310      0x00000000
0xffffd6dc:     0x08048331      0x08048419      0x00000001      0xffffd704
=> 0x8048458 <main+63>: ret
   0x8048459:   xchg   ax,ax
   0x0: Error while running hook_stop:
Cannot access memory at address 0x0
0x08048458 in main ()

ဒီလိုဆိုရင္ေတာ့ ေနာက္တစ္ခုက ret တဲ့ ။ ဒါျပီးရင္ေတာ့ ျပီးျပီဗ် ။ user function ကကုန္ျပီ။ ဘယ္သြားမွာလဲမသိဘူး စပ္စုၾကည့္ဦးမလား ၊ ret က stack ရဲ႕ အေပၚဆံုးကဟာကိုယူမွာေလ စပ္စုမွာေပါ့

(gdb) x/x 0xf7e31637
0xf7e31637 <__libc_start_main+247>:     0x8310c483
0xf7e19000 0xf7fc6000   0x1ad000        0x0 /lib32/libc-2.23.so

ဒါ library ထဲကိုေရာက္သြားျပီ ။

အဆင္ေျပမယ္ေမွ်ာ္လင့္ပါတယ္။

1 Comment

1 Trackback / Pingback

  1. 0x0A – Before you begin ROP – Legion of LOL

Comments are closed.