Hợp ngữ ● Gán 2 vào EAX ● MOV EAX, 2 ● Gán 3 vào EBX ● MOV EBX, 3 ● Tính ECX = EAX + EBX ● MOV ECX, EAX ADD ECX, EBX ● Hoặc LEA ECX, [EAX+EBX] ● Tính EDX = EAX * EBX ● ... Hợp ngữ ● Cho EAX=1, dùng một lệnh luận lý để gán EAX=-1 ● NEG EAX ● Cho EAX=FFFFFFFF, dùng một lệnh số học để gán EAX=0 ● ADD EAX, 1 ● Hoặc SUB EAX, FFFFFFFF ● Cho EAX=0, dùng một lệnh số học để gán EAX=FFFFFFFF ● SUB EAX, 1 ● Hoặc ADD EAX, FFFFFFFF Hợp ngữ ● Cho EAX là một số bất kỳ, dùng một lệnh khác MOV để gán EAX=0 ● SUB EAX, EAX ● Hoặc XOR EAX, EAX ● Hoặc AND EAX, 0 ● Hoặc LEA EAX, [0] ● Cho EAX là một số bất kỳ, dùng một lệnh khác MOV để gán EAX=FFFFFFFF ● OR EAX, FFFFFFFF Hợp ngữ ● Gán giá trị ở đỉnh ngăn xếp vào EAX ● MOV EAX, [ESP] ● Lấy ra giá trị ở đỉnh ngăn xếp vào EBX ● POP EBX ● Gán giá trị của phần tử thứ hai trên ngăn xếp vào ECX ● MOV ECX, [ESP + 4] ● Lấy ra giá trị của phần tử thứ hai trên ngăn xếp vào EDX (vẫn giữ giá trị của đỉnh ngăn xếp) ● ... Hợp ngữ ● Gán giá trị của EIP vào EAX ● ... ● Gán giá trị của EAX vào EIP ● … ● Dùng một lệnh để thực hiện phép chia lấy dư của EAX cho 16 ● AND EAX, 0x0F ● Kiểm tra nếu EAX chia hết cho 4 ● AND EAX, 0x03 Hợp ngữ ● Xét hàm ● int func(int a, int b) { int c; char d[7]; short e; return 0; } ● 2 đối số là a và b ● 3 biến nội bộ là c, d và e ● Biến a dài 4 byte, b 4, c 4, d 7 và e 2. Hợp ngữ ● Một hàm sẽ có các phần dẫn nhập, thân hàm, và kết thúc ● Dẫn nhập: ● PUSH EBP MOV EBP, ESP SUB ESP, 0x20 ● Biến nội bộ được cấp trên ngăn xếp ● Các biến nội bộ được cấp vùng nhớ theo thứ tự khai báo ● Biến được cấp vùng nhớ là bội số của 4 Hợp ngữ Hợp ngữ ● Thân hàm ● XOR EAX, EAX ● Kết quả trả về của hàm được lưu trong EAX ● Trong thân hàm, EBP không thay đổi ● Kết thúc: ● MOV ESP, EBP POP EBP RET Hợp ngữ Hợp ngữ ● Gọi hàm ● PUSH b PUSH a CALL func ● Đối số được “push” từ phải qua trái ● Vùng từ đối số đến biến nội bộ gọi là vùng nhớ (khung nhớ) ngăn xếp (stack frame) ● Vùng nhớ ngăn xếp thể hiện một hàm chưa thực thi xong ● EBP luôn chỉ đến ô “EBP cũ” trong vùng nhớ. Xác định được 1 ô → xác định các ô còn lại Hợp ngữ Hợp ngữ Hợp ngữ Tràn bộ đệm ● Dữ liệu nhập dài quá giới hạn bộ nhớ chứa nó ● Dữ liệu dư ra này có thể đè lên dữ liệu quan trọng dẫn đến cơ hội tận dụng Tràn bộ đệm ● Dữ liệu quan trọng phải nằm sau bộ đệm ● Phải tràn tới được dữ liệu quan trọng ● Dữ liệu bị ghi đè phải được sử dụng Tràn bộ đệm ● Ghi đè giá trị biến nội bộ ● Biến nội bộ nằm trong ngăn xếp ● Tràn ngăn xếp có thể đè lên biến nội bộ ● Ít bị phát hiện ● Có thể có ảnh hưởng lớn đến kết quả chương trình Tràn bộ đệm ● Xét ví dụ ● int main() { int cookie; char buf[16]; gets(buf); if (cookie==0x41424344) { puts(“You win!”); } } Tràn bộ đệm ● 2 biến nội bộ ● cookie kiểu int, 4 byte ● buf kiểu mảng char, 16 byte ● cookie nằm phía sau buf → tràn buf có thể làm thay đổi cookie ● Nhập 16 ký tự bất kỳ sẽ làm đầy buf, ký tự thứ 17 sẽ đè lên cookie → trở thành byte thấp của cookie ● Nhập 20 ký tự sẽ kiểm soát toàn bộ cookie Tràn bộ đệm