™Ác Quỷ™
27-06-2008, 02:21 PM
Một Hacker không thể không biết lập trình. Những người chỉ biết phá gọi là kẻ phá hoại. Những người chỉ biết lập trình gọi là lập trình viên. Người vừa biết lập vừa biết phá người ta gọi là Hacker :D
Programing For Hacker sẽ cho bạn biết cách lập và phá 1 cách căn bản nhất. Phần lớn nội dung của cuốn sách dùng ngôn ngữ C.
Đây là sản phẩm đầu tay của VH Stranslator Team. Các bạn có thể post bài này trên các diễn đàn khác nhưng xin đề tên VH Stranslator Team ở dưới, tôn trọng bài viết này cũng chính là tôn trọng tôi và công sức của VH Stranslator Team , đồng thờI cũng tôn trọng chính bản thân các bạn.
Trong ebook này có nhiều chỗ còn sơ sài. Nhưng tuân theo công ước Bern về quyền tác giả, VH Stranslator Team sẽ giữ nguyên bản gốc, không thêm bớt gì nhiều. Nếu có chỗ nào không hiểu các bạn cứ post câu hỏi lên để mọi người cùng giải đáp. Thêm nữa, quá trình dịch quyển ebook này có nhiều biến động, nên có nhiều sai sót. Mặc dù đã Check nhưng do thời gian quá gấp nên chưa check được toàn diện, cái này sẽ được edit lại sau.
Trong ebook có 1 vài thuật ngữ tiếng anh, xin để nguyên chính gốc vì dịch ra sẽ rất khó hiểu.
Ebook gồm 8 phần, sẽ lần lượt được post trên 4rum để các bạn thảo luận sau đó sẽ đóng gói thành ebook sau
Cuối cùng xin gửi lời cảm ơn đến toàn bộ member của VH Stranslator Team nói chung và anh m_m cùng chị tequila nói riêng đã tham gia dịch cuốn sách để cuốn sách có thể hoàn thành đúng thời hạn.
Phần I
Dịch bởi hantinhlangtu. Edit by VH Stranslator Team
Bắt Đầu :
Lập trình là gì ?Mã ( Code ) là gì ? Hacker là gì?
Có rất nhiều câu hỏi đươc đặt ra trong Forum War Industries như là :
"Có nơi nào để lấy chương trình X để xâm nhập vào máy vi tính của bạn tôi không ?"
Làm thế nào để gửi TROJAN đến 1 ai đó ?
Những câu hỏi kiểu này cho thấy , người hỏi chỉ để tâm đến các chương trình sẵn có . Và có 1 chút hiểu bít về cách hoạt động của hệ thống máy vi tính .
Họ thường đề cập đến các đoạn mã như : “script kiddies”, “skiddies” or “skidiots”
Họ cho rằng để trở thành các Hacker chỉ cần tải xuống các chương trình và chạy nó .
Theo ý kiến của riêng tôi , Hacker là người rất am hiểu về cách hoạt động của nó .
Nếu chỉ biết có khai thác hệ thống ( a script kiddie) không thôi thì chưa đủ để trở thành 1 hacker thực thụ ! Hacker can phai hieu hệ thống vào ra-bản chất của mọi vấnđề. Nếu bạn đã từng nghịch ngợm , tháo máy xén cỏ , VCR , đài cát sét , hay các thiết bị tương tự khác , thì bạn đã có ý tưởng của 1 Hacker .Sử dụng 1 đoạn ống nước để sủa ô tô gọi là "hack" .
Nếu bạn thực sự muốn trở thành 1 hacker thì bạn cần phải hiểu sự hoạt động , mọi thứ bên trong của 1 chiếc máy vi tính . Điều gì khiến nó hoạt động? Tại sao nó lại bị đổ (Crash)? Tràn bộ đệm là gì ? Làm thế nào để ra lệnh máy tính ?
Cuốn E-Book này sẽ cố gắng giúp bạn hoàn thành những việc đó !
Quy ước:
** Những bài thảo luận và ví dụ trong đây chỉ làm việc chính xác với cấu trúc x86 .
Mặc dù tương tự nhau về cấu trúc nhưng chúng khác nhau về nền tảng
**Các đoạn mã ví dụ được viết bởi C và ASM . Mục đích là dạy về C nhưng có một số đoạn mã ASM đòi hỏi cho việc giải thích những chức năng của bộ xử lý ở mức độ thấp
**Các đoạn mã chủ yếu chạy trên nền Linux nhưng có thể vẫn hoạt động dưới command line của MS window.
*** Chương trình là gì? ***
Chương trình máy tính là một loạt các câu lệnh cung cấp từng bước ra lệnh cho máy vi tính . Máy vi tính không phải là con người , không thể nào đoán trước , thêm vào hay biết được 1 bước nào đó ! Nó cần có những lời hướng dẫn ngắn gọn ( concise ) , dễ hiểu (explicit) để thực thi ngay cả đối với nhiệm vụ cơ bản nhất .
Dưới đây là ví dụ được viết bởi chương trình C . Nó có tên gọi là : “ HelloWord "
#include <stdio.h>
int main(int argc, char *argv[]){
printf(“Hello World!\n”);
}
Chúng tôi vẫn chưa đề cập sâu về vấn đề này . Chúng tôi chỉ muốn chỉ cho các bạn thấy ngôn ngữ lập trình C là gì mà thôi !
Để hiểu hơn nữa , chúng ta cần đi sâu vào cái cốt lõi của vấn đề: cái gì làm cho máy tính có thể chạy được như thế . Bạn rất muốn trở thành hacker , đúng không nào ?
*** Bộ nhớ và Base16 (cơ số 16) ***
Bộ nhớ của máy vi tính giống như một dãy các hộp đựng .Mỗi hộp này lại chứa một phần nhỏ thông tin . Trong trương hợp này , mỗi một Box tương đương với 1 Byte hay bằng 8 Bits . Điều đó có nghĩa là mỗi hộp sẽ chứa được 1 con số từ 0 đến 255. Chỉ có vậy thôi ! Nó không chứa bất cứ thứ gì khác .
Mỗi một hộp chứa 1 con số hay còn gọi là địa chỉ ( Address ) . Địa chỉ được dùng để gửi và nhận các thông tin từ các bộ nhớ . Địa chỉ được bắt đầu từ 0 và tăng dần theo quy luật cho đến bộ nhớ tối đa của máy đó . Hệ thống số đó được gọi là hexadecimal(hệ thập lục phân), viết tắt là hex. Hex is base 16.
Số Hex có dạng như sau
0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A …
** Một cách cơ bản với hệ thập phân thì các con số quay vòng tại 10 còn hệ thập lục phân thì các con số quay vòng tại 16. Như thế 10 trong hệ thập lục phân bằng 16 trong hệ thập phân
Thay vì nói " Hex " , chúng ta có thể dùng kí hiệu 0x . Vì thế ,, 0x0A có thể chuyển sang hệ thập phân . 0xFF = 255 . Những kí hiệu khác như : \x0A (bạn sẽ gặp nó trong (“shellcode”) hay như 0Ah (‘h’ kí hiệu cho hex).
Chúng ta tiếp tục nào !
Bạn sẽ tự hỏi rằng nếu như máy vi tính chỉ có thể chứa những hộp nhỏ bao gồm các số từ 0 đến 255 thì làm sao có thể làm phép toán 100* 100 ( 100 nhân 100 ) ?
Đúng là computer chỉ có thể chứa những số từ 0--255 (hex – FF) . Nhưng nó lại có thể kết hợp nhiều vị trí để tập hợp thành những con số lớn ! Không phải là cộng những con số lại với nhau , mà là kết hợp 2 vị trí . Dưới đây là ví dụ :
Đây là vị trí của 2 bộ nhớ :
Address 1000 1001
Value(Hex) 3F 2C
Bạn thấy rằng bộ nhớ tại đại chỉ 1000 lưu trữ giá trị của 0x3F ( số 63 ) và địa chỉ 1001 lưu giá trị của 0x2C( số 44 ) .Nếu bạn yêu cầu máy tính dính 2 điạ chỉ này lại với nhau , bạn sẽ có được 0x3F2C ( số 16172) . Bằng cách dính 2 Bytes liền nhau bạn có thể tạo ra số nằm trong khoảng 0 – 65535 (0xFFFF) . Nếu dính liền 4 Bytes thì chúng ta được 0 – 4294967295 (0xFFFFFFFF)
(Ví dụ cuối cùng này là rất quan trọng. Bốn bytes được đưa vào với nhau tạo thành một word trong cấu trúc x86. Ở những bộ sử lý (processors) khác thì có cỡ work khác . Hệ thống của chúng tôi sử dụng cỡ word(size word) là 32 bit hay 4bytes( vì thế cấu trúc của nó là 4 32 bit )
(lưu ý: word: từ, một đơn vị thông tin gồm các bit hoặc các byte được lập lên như là một thực thể. Và có thể được lưu trữ trong 1 vị trí. Trong các chương trình xử lý từ, word được định nghĩa là sự bao gồm một khoảng trống, nếu có, ở cuối của một chuỗi các ký tự. Ở đây cứ nên để nguyên gốc hay hơn nên tôi không dịch mà chỉ giải thích cho các bạn hiểu.)
Các giá trị đc lưu trong bộ nhớ cung cấp 1 con số . Bạn có thẻ chứa các thông tin về số . Ban cũng có thể chứa địa chỉ trong bộ nhớ để đề cập đến vị trí bộ nhớ khác . Phương thức này được gọi là : pointer(con trỏ) . 1 pointer không chứa dữ liệu mà nó trỏ tới một nơi chứa dữ liệu
. Đây là 1 khái niệm vô cùng quan trọng trong chương trình . Quan niệm về việc trỏ tới bộ nhớ là một tư tưởng lập trình cơ bản . Đây là ví dụ :
Address 3AF4 3AF5
Value D2 A4
D2A4
Address D2A4
Value 1C
Trong ví dụ trên , 2 địa chỉ 3AF4 và 3AF5 kết hợp lại cho chúng ta địa chỉ D2A4 chứa giá trị 1C . Vì vậy chúng ta có thể để địa chỉ D2A4 hoặc ra lệnh cho máy tính biết giá trị ta muốn lưu trữ tại Box Poited là 3AF4 & 5 . Hãy cố gắng nhớ đến khái niệm này bởi nó rất quan trọng . In the real world of x86, the pointer is one word in size, but the implementation is the same (trong thế giới thực của x86, con trỏ là một word trong kích thước nhưng thực hiện là như nhau.). Sang tới phần sau , Poiter size (cỡ của con trỏ) có thể không quan trọng hoạc không được nhắc đến nhưng khái niệm này vẫn rất quan trọng .
Tôi lưu ý các bạn thêm 1 điểm rằng, trước khi bắt tay vào học lập trình các bạn cần phải biết được cách đổi các hệ cơ số: 2;8;10 và 16. Vì không có thời gian và đây là bản dịch chứ không phải bài viết nên các bạn tự tìm hiểu nhé. Nếu có thắc mắc cứ post câu hỏi.
***Bộ xử lí trung tâm : The Processor (CPU)***
The Processor là trái tim của hệ thống ! Nó được thiết kế để làm những công việc :
Lấy yêu cầu từ bộ nhớ ( Fetch an instruction from memory)
Xử lý các yêu cầu đó .
Chương trình máy tính được lưu trữ trong bộ nhớ .
Ram được so sánh là chậm chạp trong việc làm thế nào để bộ xử lý mới có thể làm việc nhanh . Processor cần bộ nhớ riêng của nó để lưu lại các thông tin mà máy đang làm việc . Bộ nhớ đó được gọi là Thanh ghi.
Về phương diện vật lí thì thanh ghi nằm ngay trên bộ xử lý vì thế nó không cần thiết phải lấy bất cứ thứ gì từ trong RAM . Bộ xử lý cũng sử dụng các khoảng trống của bộ nhớ gọi là Stack (ngăn xếp). Chúng ta sẽ nói về cái này vào phần sau !
Có vô số thanh ghi trong x86 . Bây giờ chúng ta cùng định nghĩa 6 Thanh ghi :
EAX, EBX, ECX, ESP, EBP, EIP
Mỗi một thanh ghi đều bắt đầu bằng chữ cái "E" .Chỉ 32 Bít hay độ dài của 1 kí tự thanh ghi (Trước Intel 386, thanh ghi thường là 16 bit).
3 register đầu tiên EAX, EBX, and ECX được gọi là General Purpose Registers.
Chúng được sử dụng để lưu trữ và phục hồi, thêm , bớt và đổi trị số
3 register cuối cùng ESP, EBP and EIP gọi là Indexes và Pointers.Chúng giúp cho việc điều khiển sự hoạt động của các chương trình và memory referencing (tham chiếu bộ nhớ ).Đó là những thanh ghi rất quan trọng để hiểu đối với 1 hacker , và nó là trái tim của lỗi tràn bộ đệm (buffer overflow ) .Chúng ta sẽ nói về cái này sau
Ngăn xếp (stack) là một vùng của bộ nhớ được sử dụng bởi bộ sử lý có tính chất vào trước ra sau.
Hãy tưởng tượng ra 1 đống giấy trên bàn . Bạn có thể thêm hoặc bớt đi những tờ giấy . Tờ giấy mà bạn thêm vào đầu tiên là tờ cuối cùng ( nằm ở phía dưới ) . Nói theo ngôn ngữ máy tính là bạn Push (đưa vào) hay Pop (lấy ra) các giá trị . Processor có các register để chỉ các giá trị trên đầu . Đó là : ESP . và bạn có thể đoán ra , SP viết tắt cho stack pointer EBP cũng dược sử dụng trong việc trỏ tới ngăn xếp nhưng được sử dụng một cách cục bộ trong các hàm (functions). Về mặt vật lí , trong bộ nhớ , Stack băt đầu từ điểm cố định và bắt đầu giảm xuống . Ví dụ :
Nếu stack bắt đầu từ điểm có địa chỉ là 1000 và 4 bytes được push vào stack , thì điểm stack sẽ bắt đầu tiếp từ địa chỉ : 996 ( 1000-4) .
Processor lấy và thực thi các mệnh lệnh .Những lệnh đó nguồn gốc xuất phát từ những con số và được lưu trữ trong bộ nhó .Vậy làm thế nào để nó biết được yêu cầu nào sẽ được thực thi tiếp theo ?
EIP register (Instruction Pointer) trỏ tới bộ nhớ sẽ xác định yêu cầu tiếp theo đó .Register chỉ có đọc (read-only), vì thế đừng nhảy vội ! .
Nhưng bạn có thể gián tiếp thay đổi EIP đến một đia chỉ khác .: đây là chìa khóa trong việc khai thác lỗi tràn bộ đệm)
Ngôn ngữ của x86 là mã máy ( machine code). Ngôn ngữ mà con người có thể đọc được là hợp ngữ ( assembely). Chúng ta vẫn chưa cần thiêt để đi sâu vào đây . Tôi chỉ nêu ví dụ :
.file "hello.c"
.section .rodata
.LC0:
.string "Hello World.\n"
.text
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
subl $12, %esp
pushl $.LC0
call printf
addl $16, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2.2 20030222 (Red
Hat Linux 3.2.2-5)"
Đây là chương trình " Hello Word " .Nó được cung cấp bơi chương trình biên soạn GNU ( GNU compiler --sẽ nói sau ) .Chúng ta không thảo luận sâu về hợp ngữ nhưng sẽ nói chút ít về đoạn mã trên .
Dòng "MAIN " cho thấy bắt đầu chương trình.Nhìn vào phần : “.LC0" . Đoạn code ASM ra lệnh cho máy tính lưu trữ giá trị “Hello World\n” vào bộ nhớ ".LC0" .Nghe có vẻ quen quen nhỉ ^_^ . "LC0" nhắc đến 1 điểm trong bộ nhớ nơi string bắt đầu Nnó là một biểu tượng đặc biệt mà trỏ tới điểm khởi đầu trong đoạn text của bạn trong bộ nhớ.
Vì vậy thay vì phải gửi các String này mỗi khi bạn cần đến nó , thì bạn chỉ phải gửi điểm bắt đầu của String trong bộ nhớ. quá trình này hiệu quả hơn nhiều !
Cũng trong dòng ' MAIN"đó có nói đến 1 số Register mà chúng tôi đã nhắc đến trươc đó :
movl %esp, %ebp
Dòng lệnh này di chuyển (movl ,’l’ có nghĩa là chiều dài của word...) nội dung của thanh ghi ESP tới thanh ghi EBP. Nó di duyển tất cả những word (đừng quên là 1 word gồm 4 byte ) từ cái này sang cái kia
Dòng lệnh trước đó chúng ta cũng nên quan tâm một tí
pushl %ebp
Dòng lệnh này sẽ đẩy 1 kí tự ( 4 bytes) từ Register EBP vào Stack (ngăn xếp) .
The push command automatically adjusts ESP.
(lệnh push tự động điều chỉnh ESP)
subl $8, %esp
subl có nghĩa là trừ ( subtract) .Dòng lệnh này sẽ trừ 8 từ ESP . Vì sao ? Chúng ta sẽ nói sau . Nhưng đây là cách mà hợp ngữ làm để tạo thêm khoảng trống cho các biến . Đó là các khoảng trống bộ nhó mà Stack sẽ dùng sau này .Trong trương hợp này , nó sẽ tạo khoảng trống cho 2 từ hay 8 bytes .
Hãy nhìn lại các khái niệm ! bạn không cần thiêt phải hiểu các đoạn mã trên bây giờ . Điều quan trọng là bạn hiểu đựowc những khái niệm đó .
*** Ngôn ngữ lập trình ***
Ngôn ngữ lập trình rất đa dạng . Nhưng nói chung chúng được chia ra làm 3 loai:
Mã Máy ( machine code ) : đây là ngôn ngữ tự nhiện của bộ vi xử lí . Không dành cho con người . Nếu bạn thấy được cảnh những lập trình viên trong thập kỉ 60 lập trình bằng cách **c lỗ thì bạn sẽ hiểu
Chương trình được tạo ra bởi các mã số (code number) trên các đục lỗ (punch cards) và cung cấp chúng cho người đọc tại cùng 1 thời điểm.
Hợp ngữ ( assembly ) : con người có thể hiểu được mã máy . Hợp ngữ thay thế các đoạn code chỉ có riêng số bằng các đoạn code bằng chữ ví dụ như : "mov" phía trên . Bạn có thể trực tiếp tiếp xúc với register và bộ nhớ .Có 1 số thứ( không phải là tất cả )chỉ có thể được hoàn thành bằng hợp ngữ Assembly giúp cho con người nói chuyện “dễ thở” với máy tính hơn 1 chút bằng việc cho phép con người dùng 1 số lệnh (là những từ tiếng Anh đơn giản, vắn tắt), các toán tử, 1 số cấu trúc lặp, di chuyển trên vùng ghi mã chương trình trong bộ nhớ để thực thi. (ngôn ngữ này làm việc trực tiếp với các thanh ghi và bộ nhớ rất nhiều, bạn phải nắm rỏ mô hình stack của bộ nhớ...)..
Ngôn ngữ lập trình bậc cao ( High Level Languages) :
Nhóm này bao gồm rất nhiều ngôn ngữ ví như : C, C++ , Visual basic ,....
Ngôn ngữ này được sử dụng 1 cách thông dụng nhất hiện nay Bởi những lợi ích mà nó đem lại . Bạn có thể nhìn lại 2 đoạn mã bên trên . 1 cái là C , và cái kia là hợp ngũ. Bạn có thê thấy :C nói rất rõ ràng Ví dụ : printf(“Hello World\n”) Còn Hợp ngữ thì lại không làm được điều đó .
Ngôn ngữ lập trình cấp cao lại được chia ra làm 2 nhóm : Thông Dịch và biên dịch ( interpreted and compiled ) .Ngôn ngữ thông dich như Perl, dịch từng mệnh lệnh trong 1 thời gian xác định .Các khúc mắc cỏ vẻ như dễ dàng hơn với Ngôn ngữ thông dich. Lưu ý rằng máy tính để chạy chương trình của bạn phải có một trình thông dịch được cài đặt. Ví dụ : bạn không chạy được các chương trình Perl nếu như bạn chưa cài đặt Perl tại máy đó .
Ngôn ngữ biên soạn thì không bị cái giới hạn trên . Nó sẽ thực thi các mệnh lênh cùng 1 lúc ..Một lần thực thi là chung cho tất cả. Lệnh thực thi này có thể chạy với bất kể máy tính nào mà không giới hạn việc phải có một trình thông dịch được cài đặt. Trình biên dich quy định rất chặt chẽ những gì mà nó chó phép
Ngôn ngữ mà chúng ta sẽ học ở đây là C . Ngôn ngữ biên soạn . Để có thể đi tiếp nhưng phần sau . CHúng ta cần 1 trình biên soạn .Ví dụ trên tôi dùng trình biên soạn GNU C .
Câu hỏi cuối chương :
Register là gi ? Register nào nói cho bộ vi xử lí biết địa chỉ của mệnh lệnh tiếp theo sẽ được thực thi ?
Số 24 được chuyển sang HEX là gi ? 0x2E chuyển sang hệ thập phân là gi ?
Poiter là gi ?
Làm thế nào để máy tính diễn tả những số lớn hơn 255 ?
Word là gi ? độ dài của 1 Word trong cấu trúc X86 là gi ?
Hết Phần I
Phần tới : Bắt đầu với C
Programing For Hacker sẽ cho bạn biết cách lập và phá 1 cách căn bản nhất. Phần lớn nội dung của cuốn sách dùng ngôn ngữ C.
Đây là sản phẩm đầu tay của VH Stranslator Team. Các bạn có thể post bài này trên các diễn đàn khác nhưng xin đề tên VH Stranslator Team ở dưới, tôn trọng bài viết này cũng chính là tôn trọng tôi và công sức của VH Stranslator Team , đồng thờI cũng tôn trọng chính bản thân các bạn.
Trong ebook này có nhiều chỗ còn sơ sài. Nhưng tuân theo công ước Bern về quyền tác giả, VH Stranslator Team sẽ giữ nguyên bản gốc, không thêm bớt gì nhiều. Nếu có chỗ nào không hiểu các bạn cứ post câu hỏi lên để mọi người cùng giải đáp. Thêm nữa, quá trình dịch quyển ebook này có nhiều biến động, nên có nhiều sai sót. Mặc dù đã Check nhưng do thời gian quá gấp nên chưa check được toàn diện, cái này sẽ được edit lại sau.
Trong ebook có 1 vài thuật ngữ tiếng anh, xin để nguyên chính gốc vì dịch ra sẽ rất khó hiểu.
Ebook gồm 8 phần, sẽ lần lượt được post trên 4rum để các bạn thảo luận sau đó sẽ đóng gói thành ebook sau
Cuối cùng xin gửi lời cảm ơn đến toàn bộ member của VH Stranslator Team nói chung và anh m_m cùng chị tequila nói riêng đã tham gia dịch cuốn sách để cuốn sách có thể hoàn thành đúng thời hạn.
Phần I
Dịch bởi hantinhlangtu. Edit by VH Stranslator Team
Bắt Đầu :
Lập trình là gì ?Mã ( Code ) là gì ? Hacker là gì?
Có rất nhiều câu hỏi đươc đặt ra trong Forum War Industries như là :
"Có nơi nào để lấy chương trình X để xâm nhập vào máy vi tính của bạn tôi không ?"
Làm thế nào để gửi TROJAN đến 1 ai đó ?
Những câu hỏi kiểu này cho thấy , người hỏi chỉ để tâm đến các chương trình sẵn có . Và có 1 chút hiểu bít về cách hoạt động của hệ thống máy vi tính .
Họ thường đề cập đến các đoạn mã như : “script kiddies”, “skiddies” or “skidiots”
Họ cho rằng để trở thành các Hacker chỉ cần tải xuống các chương trình và chạy nó .
Theo ý kiến của riêng tôi , Hacker là người rất am hiểu về cách hoạt động của nó .
Nếu chỉ biết có khai thác hệ thống ( a script kiddie) không thôi thì chưa đủ để trở thành 1 hacker thực thụ ! Hacker can phai hieu hệ thống vào ra-bản chất của mọi vấnđề. Nếu bạn đã từng nghịch ngợm , tháo máy xén cỏ , VCR , đài cát sét , hay các thiết bị tương tự khác , thì bạn đã có ý tưởng của 1 Hacker .Sử dụng 1 đoạn ống nước để sủa ô tô gọi là "hack" .
Nếu bạn thực sự muốn trở thành 1 hacker thì bạn cần phải hiểu sự hoạt động , mọi thứ bên trong của 1 chiếc máy vi tính . Điều gì khiến nó hoạt động? Tại sao nó lại bị đổ (Crash)? Tràn bộ đệm là gì ? Làm thế nào để ra lệnh máy tính ?
Cuốn E-Book này sẽ cố gắng giúp bạn hoàn thành những việc đó !
Quy ước:
** Những bài thảo luận và ví dụ trong đây chỉ làm việc chính xác với cấu trúc x86 .
Mặc dù tương tự nhau về cấu trúc nhưng chúng khác nhau về nền tảng
**Các đoạn mã ví dụ được viết bởi C và ASM . Mục đích là dạy về C nhưng có một số đoạn mã ASM đòi hỏi cho việc giải thích những chức năng của bộ xử lý ở mức độ thấp
**Các đoạn mã chủ yếu chạy trên nền Linux nhưng có thể vẫn hoạt động dưới command line của MS window.
*** Chương trình là gì? ***
Chương trình máy tính là một loạt các câu lệnh cung cấp từng bước ra lệnh cho máy vi tính . Máy vi tính không phải là con người , không thể nào đoán trước , thêm vào hay biết được 1 bước nào đó ! Nó cần có những lời hướng dẫn ngắn gọn ( concise ) , dễ hiểu (explicit) để thực thi ngay cả đối với nhiệm vụ cơ bản nhất .
Dưới đây là ví dụ được viết bởi chương trình C . Nó có tên gọi là : “ HelloWord "
#include <stdio.h>
int main(int argc, char *argv[]){
printf(“Hello World!\n”);
}
Chúng tôi vẫn chưa đề cập sâu về vấn đề này . Chúng tôi chỉ muốn chỉ cho các bạn thấy ngôn ngữ lập trình C là gì mà thôi !
Để hiểu hơn nữa , chúng ta cần đi sâu vào cái cốt lõi của vấn đề: cái gì làm cho máy tính có thể chạy được như thế . Bạn rất muốn trở thành hacker , đúng không nào ?
*** Bộ nhớ và Base16 (cơ số 16) ***
Bộ nhớ của máy vi tính giống như một dãy các hộp đựng .Mỗi hộp này lại chứa một phần nhỏ thông tin . Trong trương hợp này , mỗi một Box tương đương với 1 Byte hay bằng 8 Bits . Điều đó có nghĩa là mỗi hộp sẽ chứa được 1 con số từ 0 đến 255. Chỉ có vậy thôi ! Nó không chứa bất cứ thứ gì khác .
Mỗi một hộp chứa 1 con số hay còn gọi là địa chỉ ( Address ) . Địa chỉ được dùng để gửi và nhận các thông tin từ các bộ nhớ . Địa chỉ được bắt đầu từ 0 và tăng dần theo quy luật cho đến bộ nhớ tối đa của máy đó . Hệ thống số đó được gọi là hexadecimal(hệ thập lục phân), viết tắt là hex. Hex is base 16.
Số Hex có dạng như sau
0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A …
** Một cách cơ bản với hệ thập phân thì các con số quay vòng tại 10 còn hệ thập lục phân thì các con số quay vòng tại 16. Như thế 10 trong hệ thập lục phân bằng 16 trong hệ thập phân
Thay vì nói " Hex " , chúng ta có thể dùng kí hiệu 0x . Vì thế ,, 0x0A có thể chuyển sang hệ thập phân . 0xFF = 255 . Những kí hiệu khác như : \x0A (bạn sẽ gặp nó trong (“shellcode”) hay như 0Ah (‘h’ kí hiệu cho hex).
Chúng ta tiếp tục nào !
Bạn sẽ tự hỏi rằng nếu như máy vi tính chỉ có thể chứa những hộp nhỏ bao gồm các số từ 0 đến 255 thì làm sao có thể làm phép toán 100* 100 ( 100 nhân 100 ) ?
Đúng là computer chỉ có thể chứa những số từ 0--255 (hex – FF) . Nhưng nó lại có thể kết hợp nhiều vị trí để tập hợp thành những con số lớn ! Không phải là cộng những con số lại với nhau , mà là kết hợp 2 vị trí . Dưới đây là ví dụ :
Đây là vị trí của 2 bộ nhớ :
Address 1000 1001
Value(Hex) 3F 2C
Bạn thấy rằng bộ nhớ tại đại chỉ 1000 lưu trữ giá trị của 0x3F ( số 63 ) và địa chỉ 1001 lưu giá trị của 0x2C( số 44 ) .Nếu bạn yêu cầu máy tính dính 2 điạ chỉ này lại với nhau , bạn sẽ có được 0x3F2C ( số 16172) . Bằng cách dính 2 Bytes liền nhau bạn có thể tạo ra số nằm trong khoảng 0 – 65535 (0xFFFF) . Nếu dính liền 4 Bytes thì chúng ta được 0 – 4294967295 (0xFFFFFFFF)
(Ví dụ cuối cùng này là rất quan trọng. Bốn bytes được đưa vào với nhau tạo thành một word trong cấu trúc x86. Ở những bộ sử lý (processors) khác thì có cỡ work khác . Hệ thống của chúng tôi sử dụng cỡ word(size word) là 32 bit hay 4bytes( vì thế cấu trúc của nó là 4 32 bit )
(lưu ý: word: từ, một đơn vị thông tin gồm các bit hoặc các byte được lập lên như là một thực thể. Và có thể được lưu trữ trong 1 vị trí. Trong các chương trình xử lý từ, word được định nghĩa là sự bao gồm một khoảng trống, nếu có, ở cuối của một chuỗi các ký tự. Ở đây cứ nên để nguyên gốc hay hơn nên tôi không dịch mà chỉ giải thích cho các bạn hiểu.)
Các giá trị đc lưu trong bộ nhớ cung cấp 1 con số . Bạn có thẻ chứa các thông tin về số . Ban cũng có thể chứa địa chỉ trong bộ nhớ để đề cập đến vị trí bộ nhớ khác . Phương thức này được gọi là : pointer(con trỏ) . 1 pointer không chứa dữ liệu mà nó trỏ tới một nơi chứa dữ liệu
. Đây là 1 khái niệm vô cùng quan trọng trong chương trình . Quan niệm về việc trỏ tới bộ nhớ là một tư tưởng lập trình cơ bản . Đây là ví dụ :
Address 3AF4 3AF5
Value D2 A4
D2A4
Address D2A4
Value 1C
Trong ví dụ trên , 2 địa chỉ 3AF4 và 3AF5 kết hợp lại cho chúng ta địa chỉ D2A4 chứa giá trị 1C . Vì vậy chúng ta có thể để địa chỉ D2A4 hoặc ra lệnh cho máy tính biết giá trị ta muốn lưu trữ tại Box Poited là 3AF4 & 5 . Hãy cố gắng nhớ đến khái niệm này bởi nó rất quan trọng . In the real world of x86, the pointer is one word in size, but the implementation is the same (trong thế giới thực của x86, con trỏ là một word trong kích thước nhưng thực hiện là như nhau.). Sang tới phần sau , Poiter size (cỡ của con trỏ) có thể không quan trọng hoạc không được nhắc đến nhưng khái niệm này vẫn rất quan trọng .
Tôi lưu ý các bạn thêm 1 điểm rằng, trước khi bắt tay vào học lập trình các bạn cần phải biết được cách đổi các hệ cơ số: 2;8;10 và 16. Vì không có thời gian và đây là bản dịch chứ không phải bài viết nên các bạn tự tìm hiểu nhé. Nếu có thắc mắc cứ post câu hỏi.
***Bộ xử lí trung tâm : The Processor (CPU)***
The Processor là trái tim của hệ thống ! Nó được thiết kế để làm những công việc :
Lấy yêu cầu từ bộ nhớ ( Fetch an instruction from memory)
Xử lý các yêu cầu đó .
Chương trình máy tính được lưu trữ trong bộ nhớ .
Ram được so sánh là chậm chạp trong việc làm thế nào để bộ xử lý mới có thể làm việc nhanh . Processor cần bộ nhớ riêng của nó để lưu lại các thông tin mà máy đang làm việc . Bộ nhớ đó được gọi là Thanh ghi.
Về phương diện vật lí thì thanh ghi nằm ngay trên bộ xử lý vì thế nó không cần thiết phải lấy bất cứ thứ gì từ trong RAM . Bộ xử lý cũng sử dụng các khoảng trống của bộ nhớ gọi là Stack (ngăn xếp). Chúng ta sẽ nói về cái này vào phần sau !
Có vô số thanh ghi trong x86 . Bây giờ chúng ta cùng định nghĩa 6 Thanh ghi :
EAX, EBX, ECX, ESP, EBP, EIP
Mỗi một thanh ghi đều bắt đầu bằng chữ cái "E" .Chỉ 32 Bít hay độ dài của 1 kí tự thanh ghi (Trước Intel 386, thanh ghi thường là 16 bit).
3 register đầu tiên EAX, EBX, and ECX được gọi là General Purpose Registers.
Chúng được sử dụng để lưu trữ và phục hồi, thêm , bớt và đổi trị số
3 register cuối cùng ESP, EBP and EIP gọi là Indexes và Pointers.Chúng giúp cho việc điều khiển sự hoạt động của các chương trình và memory referencing (tham chiếu bộ nhớ ).Đó là những thanh ghi rất quan trọng để hiểu đối với 1 hacker , và nó là trái tim của lỗi tràn bộ đệm (buffer overflow ) .Chúng ta sẽ nói về cái này sau
Ngăn xếp (stack) là một vùng của bộ nhớ được sử dụng bởi bộ sử lý có tính chất vào trước ra sau.
Hãy tưởng tượng ra 1 đống giấy trên bàn . Bạn có thể thêm hoặc bớt đi những tờ giấy . Tờ giấy mà bạn thêm vào đầu tiên là tờ cuối cùng ( nằm ở phía dưới ) . Nói theo ngôn ngữ máy tính là bạn Push (đưa vào) hay Pop (lấy ra) các giá trị . Processor có các register để chỉ các giá trị trên đầu . Đó là : ESP . và bạn có thể đoán ra , SP viết tắt cho stack pointer EBP cũng dược sử dụng trong việc trỏ tới ngăn xếp nhưng được sử dụng một cách cục bộ trong các hàm (functions). Về mặt vật lí , trong bộ nhớ , Stack băt đầu từ điểm cố định và bắt đầu giảm xuống . Ví dụ :
Nếu stack bắt đầu từ điểm có địa chỉ là 1000 và 4 bytes được push vào stack , thì điểm stack sẽ bắt đầu tiếp từ địa chỉ : 996 ( 1000-4) .
Processor lấy và thực thi các mệnh lệnh .Những lệnh đó nguồn gốc xuất phát từ những con số và được lưu trữ trong bộ nhó .Vậy làm thế nào để nó biết được yêu cầu nào sẽ được thực thi tiếp theo ?
EIP register (Instruction Pointer) trỏ tới bộ nhớ sẽ xác định yêu cầu tiếp theo đó .Register chỉ có đọc (read-only), vì thế đừng nhảy vội ! .
Nhưng bạn có thể gián tiếp thay đổi EIP đến một đia chỉ khác .: đây là chìa khóa trong việc khai thác lỗi tràn bộ đệm)
Ngôn ngữ của x86 là mã máy ( machine code). Ngôn ngữ mà con người có thể đọc được là hợp ngữ ( assembely). Chúng ta vẫn chưa cần thiêt để đi sâu vào đây . Tôi chỉ nêu ví dụ :
.file "hello.c"
.section .rodata
.LC0:
.string "Hello World.\n"
.text
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
subl $12, %esp
pushl $.LC0
call printf
addl $16, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2.2 20030222 (Red
Hat Linux 3.2.2-5)"
Đây là chương trình " Hello Word " .Nó được cung cấp bơi chương trình biên soạn GNU ( GNU compiler --sẽ nói sau ) .Chúng ta không thảo luận sâu về hợp ngữ nhưng sẽ nói chút ít về đoạn mã trên .
Dòng "MAIN " cho thấy bắt đầu chương trình.Nhìn vào phần : “.LC0" . Đoạn code ASM ra lệnh cho máy tính lưu trữ giá trị “Hello World\n” vào bộ nhớ ".LC0" .Nghe có vẻ quen quen nhỉ ^_^ . "LC0" nhắc đến 1 điểm trong bộ nhớ nơi string bắt đầu Nnó là một biểu tượng đặc biệt mà trỏ tới điểm khởi đầu trong đoạn text của bạn trong bộ nhớ.
Vì vậy thay vì phải gửi các String này mỗi khi bạn cần đến nó , thì bạn chỉ phải gửi điểm bắt đầu của String trong bộ nhớ. quá trình này hiệu quả hơn nhiều !
Cũng trong dòng ' MAIN"đó có nói đến 1 số Register mà chúng tôi đã nhắc đến trươc đó :
movl %esp, %ebp
Dòng lệnh này di chuyển (movl ,’l’ có nghĩa là chiều dài của word...) nội dung của thanh ghi ESP tới thanh ghi EBP. Nó di duyển tất cả những word (đừng quên là 1 word gồm 4 byte ) từ cái này sang cái kia
Dòng lệnh trước đó chúng ta cũng nên quan tâm một tí
pushl %ebp
Dòng lệnh này sẽ đẩy 1 kí tự ( 4 bytes) từ Register EBP vào Stack (ngăn xếp) .
The push command automatically adjusts ESP.
(lệnh push tự động điều chỉnh ESP)
subl $8, %esp
subl có nghĩa là trừ ( subtract) .Dòng lệnh này sẽ trừ 8 từ ESP . Vì sao ? Chúng ta sẽ nói sau . Nhưng đây là cách mà hợp ngữ làm để tạo thêm khoảng trống cho các biến . Đó là các khoảng trống bộ nhó mà Stack sẽ dùng sau này .Trong trương hợp này , nó sẽ tạo khoảng trống cho 2 từ hay 8 bytes .
Hãy nhìn lại các khái niệm ! bạn không cần thiêt phải hiểu các đoạn mã trên bây giờ . Điều quan trọng là bạn hiểu đựowc những khái niệm đó .
*** Ngôn ngữ lập trình ***
Ngôn ngữ lập trình rất đa dạng . Nhưng nói chung chúng được chia ra làm 3 loai:
Mã Máy ( machine code ) : đây là ngôn ngữ tự nhiện của bộ vi xử lí . Không dành cho con người . Nếu bạn thấy được cảnh những lập trình viên trong thập kỉ 60 lập trình bằng cách **c lỗ thì bạn sẽ hiểu
Chương trình được tạo ra bởi các mã số (code number) trên các đục lỗ (punch cards) và cung cấp chúng cho người đọc tại cùng 1 thời điểm.
Hợp ngữ ( assembly ) : con người có thể hiểu được mã máy . Hợp ngữ thay thế các đoạn code chỉ có riêng số bằng các đoạn code bằng chữ ví dụ như : "mov" phía trên . Bạn có thể trực tiếp tiếp xúc với register và bộ nhớ .Có 1 số thứ( không phải là tất cả )chỉ có thể được hoàn thành bằng hợp ngữ Assembly giúp cho con người nói chuyện “dễ thở” với máy tính hơn 1 chút bằng việc cho phép con người dùng 1 số lệnh (là những từ tiếng Anh đơn giản, vắn tắt), các toán tử, 1 số cấu trúc lặp, di chuyển trên vùng ghi mã chương trình trong bộ nhớ để thực thi. (ngôn ngữ này làm việc trực tiếp với các thanh ghi và bộ nhớ rất nhiều, bạn phải nắm rỏ mô hình stack của bộ nhớ...)..
Ngôn ngữ lập trình bậc cao ( High Level Languages) :
Nhóm này bao gồm rất nhiều ngôn ngữ ví như : C, C++ , Visual basic ,....
Ngôn ngữ này được sử dụng 1 cách thông dụng nhất hiện nay Bởi những lợi ích mà nó đem lại . Bạn có thể nhìn lại 2 đoạn mã bên trên . 1 cái là C , và cái kia là hợp ngũ. Bạn có thê thấy :C nói rất rõ ràng Ví dụ : printf(“Hello World\n”) Còn Hợp ngữ thì lại không làm được điều đó .
Ngôn ngữ lập trình cấp cao lại được chia ra làm 2 nhóm : Thông Dịch và biên dịch ( interpreted and compiled ) .Ngôn ngữ thông dich như Perl, dịch từng mệnh lệnh trong 1 thời gian xác định .Các khúc mắc cỏ vẻ như dễ dàng hơn với Ngôn ngữ thông dich. Lưu ý rằng máy tính để chạy chương trình của bạn phải có một trình thông dịch được cài đặt. Ví dụ : bạn không chạy được các chương trình Perl nếu như bạn chưa cài đặt Perl tại máy đó .
Ngôn ngữ biên soạn thì không bị cái giới hạn trên . Nó sẽ thực thi các mệnh lênh cùng 1 lúc ..Một lần thực thi là chung cho tất cả. Lệnh thực thi này có thể chạy với bất kể máy tính nào mà không giới hạn việc phải có một trình thông dịch được cài đặt. Trình biên dich quy định rất chặt chẽ những gì mà nó chó phép
Ngôn ngữ mà chúng ta sẽ học ở đây là C . Ngôn ngữ biên soạn . Để có thể đi tiếp nhưng phần sau . CHúng ta cần 1 trình biên soạn .Ví dụ trên tôi dùng trình biên soạn GNU C .
Câu hỏi cuối chương :
Register là gi ? Register nào nói cho bộ vi xử lí biết địa chỉ của mệnh lệnh tiếp theo sẽ được thực thi ?
Số 24 được chuyển sang HEX là gi ? 0x2E chuyển sang hệ thập phân là gi ?
Poiter là gi ?
Làm thế nào để máy tính diễn tả những số lớn hơn 255 ?
Word là gi ? độ dài của 1 Word trong cấu trúc X86 là gi ?
Hết Phần I
Phần tới : Bắt đầu với C