|
|
@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.
|
|
|
@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 đó.
|
|
|
@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.
|
|
|
@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;
}
|
|
|
@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.
|
|
|
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;
}
|
|
|
@rickb: ơ giận àh? Nếu bạn thật sự nghĩ trình độ của bạn không được như tớ, thì sao không nghe lời khuyên của tớ nhỉ? Tớ khuyên chân thành mà, không có ý xốc xiểm gì đâu nhá.
PS: mà bạn không biết tớ là ai đâu. Không phải là như bạn nghĩ đâu.
|
|
|
meomeo_bebong wrote:
100k/số thì em xin kiếu. Em down chùa của các anh còn hơn smilie
ôi thế thì các anh của em ngu thật.
@rickb: tớ thấy mua mấy cái magazine này chỉ tổ phí tiền. Một cuốn chắc chỉ 1,2 bài đọc được, còn lại toàn nói nhảm với quảng cáo. Bài đọc được cũng thường thiếu trước hụt sau, do kô có đủ thời gian, không gian (và cả động lực của tác giả) để viết cho nó đầy đủ hay ho.
Tớ thấy hoặc là khôn như bạn meomeo_bebong (và phải tìm mấy thằng ngu ngu bỏ tiền ra mua nữa), hoặc là để dành tiền mua sách còn hơn. 1 triệu thì mua cũng được 2-3 cuốn sách rồi.
|
|
|
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]);
}
|
|
|
hay quá, giờ mình mới biết Backtrack là để nghe nhạc. sáng tạo thế này mới xứng đáng là hacker chứ. cảm ơn bạn Murin nhé.
|
|
|
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.
|
|
|
thêm cái Security assessment of the Internet Protocol luôn cho đủ bộ http://www.cpni.gov.uk/Docs/InternetProtocol.pdf
|
|
|
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.
|
|
|
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);
}
}
|
|
|
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 đó.
|
|
|
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]);
}
|
|
|
@secmask: có thể gcc của mình nó tạo kết quả khác. Để thuận tiện, mình gửi binary lên đây cho các bạn xem thử: http://www.mediafire.com/?ytodbt4nhwl
Nhớ cẩn thận nha, mình ít bao giờ chạy binary lạ mà không xem xét trước lắm.
|
|
|
@secmask: chạy thử lại nhiều lần xem sao? Xem có lần nào bị đứng im không?
|
|
|
@lamer: đúng rồi đó bạn. Thí dụ mình chạy thế này:
Code:
$ ./test `perl -e 'print "A" x 10'`
Lẽ ra nó phải xuất ra 10 chữ A, nhưng đằng này nó đứng luôn, không xuất gì ra màn hình. strace cũng không thấy gì hết, cứ đứng im.
|
|
|
Chào các bạn,
Mình có chương trình C đơn giản thế này mà không hiểu sao khi biên dịch bằng gcc-4.x rồi chạy thì nó cứ đứng khựng lại, không biết sai chỗ nào?
Code:
void weird_print(char *str)
{
char buffer[100];
int n=0;
for (n=0; n<=100;n++)
buffer[n]=str[n];
printf("%s\n", buffer);
}
int main(int argc, char *argv[])
{
if (argc>1) weird_print(argv[1]);
return 0;
}
|
|
|
ơ nếu cho lựa chọn, mình vẫn lựa pubkey + passphrase, dẫu gì cũng là 2 yếu tố.
@IQ: mình nghĩ chỉ có cái ý vài anh chàng sysadmin generate key không có passphrase là make sense thôi. chứ còn ý còn lại, private key có thể bị copy, vì buộc phải lưu trên máy của user thì có copy cũng có làm được gì đâu, nếu có đặt passphrase.
vả lại ý 1 cũng tương đương như password thôi, phải bảo vệ cái key đó. nếu không áp được bằng kỹ thuật, thì áp bằng hành chính, cứ một đợt audit, phát hiện anh nào không đặt passphrase, hay share private key tùm lum thì kỷ luật, vậy thôi.
thangdiablo wrote:
Trong quá trình chuyển cái public key cho anh sysadmin này có nhiều trường hợp nguy hiểm có thể xảy ra.
nguy hiểm thế nào vậy bạn?
thangdiablo wrote:
Cái session key dùng trong trường hợp client login vào SSH Server mà không sử dụng private key.
)
|
|
|
@281: cá nhân hoặc nhóm kô có tư cách pháp nhân được hông? Đảm bảo làm ăn ngon nha bạn Thụy .
|
|
|
Àh quên trả lời bạn lamer: dùng cái nào cũng có rủi ro như nhau. Bạn nào nghĩ dùng public-key an toàn hơn thì thử nhớ lại cái vụ một thằng developer của Debian nó sửa cái PRNG trong gói OpenSSL đi.
|
|
|
ơ bạn thangdiablo với bạn quanta nói gì thế nhỉ?
quanta wrote:
- password được truyền đi trên mạng nên có thể bị sniff
có password nào được truyền dạng plaintext trên mạng đâu bạn?
thangdiablo wrote:
Lúc này, PIN code mà client gõ vào + public key được gửi về từ servers hay devices sẽ kết hợp với nhau và tạo ra 1 session key.
Session key này được mã hóa và chuyển đi trên đường truyền.
...
Vì bản thân public key do SSH servers tạo ra và client chỉ dùng cái public key đó + với cái PIN code = session key và gửi đi.
thế cái session key này được dùng làm gì? theo mình biết thì passphrase mà user nhập vào là để decrypt cái local private key (để dùng cho việc authentication), làm gì có liên quan đến việc tạo session key nhỉ?
|
|
|
Khi làm DoS, vấn đề không phải là bạn bring down được một hệ thống hay không, mà là bạn làm được chuyện đó trong bao lâu.
Một tấn công DoS hiệu quả phải là một tấn công mà bạn hoàn toàn chủ động về thời gian, kiểu như muốn hệ thống nào đó chết lúc nào là nó phải chết lúc đó, và chết cho đến khi bạn muốn nó sống lại, bất kể bất kỳ thao tác prevention/reaction nào của người quản lý hệ thống đó.
Kiểu DoS mà bạn antidos đề cập, như mình đã mô tả ý tưởng ở trên, không thể làm được điều này, bởi lẽ chỉ cần người quản trị có mặt để block nhóm các IP tấn công là xong. Bọn tấn công DoS cũng không dại gì chơi cái trò mà antidos đang chơi, bởi nguy cơ bị lần ra là rất cao. Cứ xflash mà quất cho nó an toàn, nhỉ?
Nên dẫu phát hiện của bạn antidos có gì đó mới, điều mà mình nghi ngờ, thì mình nghĩ nó cũng chẳng ảnh hưởng gì đến hòa bình thế giới. Có thể nó có gì đó hay ho trong cách triển khai, nhưng chẳng có ứng dụng thực tế.
Vậy thôi cho vào /dev/null nha các bạn?
|
|
|
antidos wrote:
Tôi cũng vừa đọc về sockstress, khá thú vị, vì trong bước đầu thử nghiệm phần mềm tấn công của tôi, tôi cũng đạt được các hiệu ứng giống hệt như các mô tả của sockstress, tuy nhiên sockstress tạo rất nhiều connection nên module recent của iptables có thể chặn được, còn cuộc tấn công của tôi hiệu quả hơn ngay cả khi nạn nhân dùng ipt_recent.ko. Tôi đoán rằng 1 site như hva thì connlimit và recent là 2 thứ đương nhiên phải triển khai, nhưng rất tiếc cuộc tấn công của tôi được thiết kế để qua mặt 2 hình thức bảo vệ này. Mặt khác bản cài đặt của tôi cũng an toàn hơn, cho phép huỷ cuộc tấn công để mọi người có thể truy cập lại được như cũ.
mình đoán là cái cách mà bạn làm với sockstress chỉ là khác nhau về hình thức triển khai thôi, chứ thật ra cũng đều giống nhau về ý tưởng: làm hết resource của host bằng cách mở càng nhiều càng tốt tcp connection.
để qua mặt connlimit và recent thì không quá khó, chỉ cần có một dãy public IP, càng nhiều càng tốt. tiếp theo thì cần có 2 host (1 cũng được), host A thì thay phiên dùng raw packet gửi SYN đến HVA, sử dụng một trong các public IP. host B còn lại (được cấu hình trên router) nhận các packet ACK/SYN trả về từ HVA (bằng cách sniff trực tiếp), và tạo ACK/SYN giả để hoàn thành 3-way handshake.
với cách làm này, phía attacker chẳng cần phải keep track gì hết các tcp connection, nên sẽ rất nhẹ nhàng. ngược lại, phía HVA, phải tốn resource (memory, file descriptor...) cho mỗi tcp connection, nên sẽ rất nhanh bị quá tải. muốn hủy tấn công thì từ chỉ cần ra lệnh cho host B gửi FIN hay RST đến HVA, để đóng kết nối, giải tỏa resource là xong.
điều cuối cùng mình muốn nói là việc úp úp mở mở này chẳng hay ho gì. nó chẳng làm cho bạn trở nên smart hơn trong mắt người khác đâu.
|
|
|
sockstress? mình nghĩ tất cả các bài theo kiểu úp úp mở mở thế này thì nên cho vào sọt rác. empirical data cho thấy 100% là sẽ không có gì mới.
|
|
|
cấu hình cho router/switch quăng log về một cái syslog server khi có ai vào cấu hình là dễ nhất.
|
|
|
coi bản tiếng Anh chính thức của NIST luông cho rồi http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
|
|
ơ hacker gì mà xài tool cũng không nên thân?
|
|
|
|
|
|
|