Câu hỏi: IAM302 - Phần 4: Python và hợp ngữ x86
22 câu trắc nghiệm kèm lời giải của môn IAM302 - Phân tích mã độc và kỹ thuật dịch ngược, xếp theo thứ tự nhập vào ngân hàng.
Danh sách câu hỏi
20/22 câuCòn 2
1What will be the output of the following Python code?4 lựa chọncó code
def foo():
try:
return 1
finally:
return 2
k = foo()
print(k)Aerror, there is more than one return statement in a single try-finally block
B3
C2
D1
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "2". Trong Python, khối finally luôn chạy trước khi hàm thực sự rời đi, kể cả khi khối try đã gặp return. Lần theo: foo() vào try, gặp return 1 nên giá trị 1 được chuẩn bị làm kết quả, nhưng trước khi trả về, trình thông dịch chạy finally; ở đó return 2 thay thế giá trị đang chờ, nên foo() trả 2, k nhận 2 và print(k) in ra 2. "1" sai vì bỏ qua việc return trong finally ghi đè return trong try. "3" sai vì không có phép cộng nào, hai giá trị không gộp lại với nhau. "error, there is more than one return statement in a single try-finally block" sai vì Python cho phép nhiều câu return trong một hàm, đặt trong cả try lẫn finally; đây là cú pháp hợp lệ, chỉ là cách viết dễ gây nhầm vì nó nuốt mất giá trị trả về của try, và cả ngoại lệ nếu try ném ra.
ATrue
BFalse
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "False". Trong trình thông dịch tương tác (standard Python shell, dấu nhắc >>>), một dòng trống được hiểu là kết thúc khối lệnh ghép đang nhập ở dấu nhắc tiếp tục (...). Vì vậy nếu dán một vòng lặp for có dòng trống ở giữa thân, shell đóng khối for ngay tại dòng trống và chạy nó, còn các dòng thụt lề phía sau bị coi là lệnh mới mở đầu bằng khoảng trắng nên sinh IndentationError: unexpected indent. Cùng đoạn mã đó chạy bình thường khi lưu thành tệp .py, vì khi đọc tệp trình thông dịch bỏ qua dòng trống. Do đó khẳng định luôn chạy không lỗi là sai; chọn "True" là bỏ qua quy tắc dòng trống riêng của chế độ tương tác, điều cần nhớ khi thử nhanh các đoạn script phân tích mã độc trong shell.
A[-4, 3, -2, 1]
B[3, 1, -2, -4]
C[1, -2, 3, -4]
D[-4, -2, 1, 3]
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "[-4, 3, -2, 1]". Hàm sorted trong Python trả về một danh sách mới đã sắp; tham số key=abs nghĩa là so sánh theo giá trị tuyệt đối của từng phần tử chứ không theo chính phần tử, còn reverse=True đảo thành thứ tự giảm dần. Lần theo từng bước: giá trị tuyệt đối của -4, 1, -2, 3 lần lượt là 4, 1, 2, 3; xếp giảm dần được 4, 3, 2, 1, tương ứng các phần tử gốc -4, 3, -2, 1, và dấu âm vẫn được giữ vì key chỉ dùng để so sánh chứ không biến đổi phần tử trả về. "[3, 1, -2, -4]" là kết quả khi sắp giảm theo giá trị thật, tức bỏ key=abs mà chỉ giữ reverse=True. "[1, -2, 3, -4]" là thứ tự tăng dần theo giá trị tuyệt đối, tức có key=abs nhưng quên reverse. "[-4, -2, 1, 3]" là thứ tự tăng dần theo giá trị thật, bỏ qua cả key lẫn reverse.
A4
B4.6
C5
D4.5
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "5". Hàm round khi chỉ có một đối số sẽ làm tròn tới số nguyên gần nhất và trả về kiểu int. Giá trị 4.576 nằm giữa 4 và 5, phần lẻ 0.576 lớn hơn 0.5 nên gần 5 hơn, kết quả là 5. "4" là kết quả của việc cắt bỏ phần thập phân như int(4.576) hay math.floor(4.576), không phải làm tròn. "4.6" là kết quả của round(4.576, 1), tức làm tròn tới một chữ số sau dấu thập phân, nhưng biểu thức không truyền đối số thứ hai. "4.5" không khớp với cách làm tròn nào của 4.576; quy tắc làm tròn về số chẵn của Python chỉ có tác dụng khi giá trị nằm đúng giữa hai số nguyên như 4.5, không liên quan tới trường hợp này.
AIt stores the physical addresses of running processes
BIt allocates memory for user-mode applications
CIt manages kernel-mode memory exclusively
DIt maps virtual addresses to physical memory via page tables
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "It maps virtual addresses to physical memory via page tables". Trong phân trang x86 32 bit, thanh ghi CR3 trỏ tới Page Directory (thư mục trang); khi CPU dịch một địa chỉ ảo, 10 bit cao chọn một mục PDE trong thư mục trang, mục này trỏ tới một Page Table (bảng trang), 10 bit kế tiếp chọn mục PTE chứa khung trang vật lý, và 12 bit thấp là độ lệch trong trang 4 KB. Như vậy thư mục trang là tầng đầu của chuỗi ánh xạ địa chỉ ảo sang vật lý, mỗi tiến trình có thư mục riêng. Bác: "It stores the physical addresses of running processes" sai vì danh sách tiến trình nằm trong cấu trúc của nhân như EPROCESS, thư mục trang chỉ chứa mục ánh xạ. "It allocates memory for user-mode applications" là việc của trình quản lý bộ nhớ hệ điều hành qua VirtualAlloc hay HeapAlloc; thư mục trang chỉ phản ánh kết quả cấp phát. "It manages kernel-mode memory exclusively" sai vì nó ánh xạ cả vùng người dùng lẫn vùng nhân trong không gian địa chỉ.
AIt executes faster than compiled languages like C++
BIt reduces code size significantly compared to C++ or Java
CIt is restricted to Windows platforms only
DIt lacks support for object-oriented programming
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "It reduces code size significantly compared to C++ or Java". Python có cú pháp gọn, kiểu động, thư viện chuẩn và thư viện bên thứ ba phong phú như pefile, yara-python, capstone, nên cùng một việc như đọc tiêu đề PE hay giải mã chuỗi được viết bằng ít dòng hơn hẳn so với C++ hay Java; nhờ vậy người phân tích viết nhanh script tự động hoá và sửa ngay khi gặp mẫu mới. Bác: "It executes faster than compiled languages like C++" sai, Python được thông dịch nên thường chạy chậm hơn mã C++ đã biên dịch; lợi thế của nó là tốc độ viết chứ không phải tốc độ chạy. "It is restricted to Windows platforms only" sai vì Python chạy đa nền tảng trên Windows, Linux và macOS, đó cũng là lý do các công cụ như Volatility dùng được ở mọi nơi. "It lacks support for object-oriented programming" sai vì Python hỗ trợ đầy đủ lớp, kế thừa và đa hình.
APuts the literal string "ebx" into eax
BPuts the contents of memory pointed to by ebx into eax
CPuts the contents of eax into ebx
DPuts the contents of ebx into eax
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "Puts the contents of memory pointed to by ebx into eax". Trong cú pháp Intel, lệnh mov đích, nguồn chép giá trị từ toán hạng nguồn sang toán hạng đích, còn dấu ngoặc vuông nghĩa là truy cập bộ nhớ gián tiếp: [ebx] là ô nhớ có địa chỉ bằng giá trị đang nằm trong ebx. Vì vậy mov eax,[ebx] đọc 4 byte tại địa chỉ mà ebx trỏ tới rồi nạp vào eax, giống phép giải tham chiếu con trỏ trong C. Bác: "Puts the literal string "ebx" into eax" sai vì ebx là tên thanh ghi, hợp ngữ không coi nó là chuỗi ký tự. "Puts the contents of eax into ebx" đảo ngược chiều chép: toán hạng đầu là đích nên eax nhận dữ liệu chứ không gửi đi. "Puts the contents of ebx into eax" là tác dụng của lệnh mov eax, ebx không có ngoặc vuông, chép chính giá trị địa chỉ chứ không đọc ô nhớ mà nó trỏ tới.
ABroken link
BCode to be executed if the result was zero
CCode to be executed if the result was not zero
DJust a decoration
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "Code to be executed if the result was not zero". Trong chế độ đồ thị (graph view) của IDA Pro, sau một lệnh nhảy có điều kiện có hai mũi tên: xanh lá chỉ nhánh khi lệnh nhảy được thực hiện, đỏ chỉ nhánh khi không nhảy và chạy tiếp lệnh kế. JZ (jump if zero) nhảy khi cờ ZF bật, tức kết quả của phép so sánh hay phép tính ngay trước bằng 0; vậy mũi tên đỏ dẫn tới mã chạy khi kết quả khác 0. Có bản đáp án lưu hành chọn "Broken link", nhưng không theo được vì IDA không dùng màu đỏ để báo liên kết hỏng; nhầm lẫn có thể đến từ cửa sổ mũi tên ở lề trái của chế độ văn bản, nơi mũi tên đỏ mang nghĩa khác là đích nhảy nằm ngoài hàm hiện tại, vẫn không phải liên kết hỏng. "Code to be executed if the result was zero" là nhánh của mũi tên xanh lá. "Just a decoration" sai vì màu mũi tên mang thông tin về luồng điều khiển.
AJava
BPython
CC++
DJavaScript
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "Python". Python là ngôn ngữ thông dịch, cú pháp gọn, chạy đa nền tảng và có hệ sinh thái thư viện chuyên cho phân tích mã độc: pefile đọc cấu trúc PE, yara-python chạy luật YARA, capstone dịch ngược mã máy, Volatility phân tích bộ nhớ; IDA, Ghidra và x64dbg đều cho viết script bằng Python. Nhờ vậy người phân tích tự động hoá nhanh các việc như giải mã chuỗi hay trích cấu hình của mẫu. Bác: "Java" chạy đa nền tảng nhưng dài dòng hơn, ít được chọn để viết công cụ phân tích nhanh. "C++" dùng để viết công cụ cần tốc độ hay plugin mức thấp, và người phân tích cần đọc hiểu nó vì nhiều mã độc viết bằng C++, nhưng nó không tiện cho script viết nhanh. "JavaScript" chủ yếu gặp khi phân tích mã độc trên web hay tệp script độc hại, không phải ngôn ngữ đa dụng cho công cụ phân tích.
AEvery object in Python doesn't have a unique id
BIn Python Id function returns the identity of the object
CNone of the mentioned
DAll of the mentioned
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "In Python Id function returns the identity of the object". Hàm id() trả về một số nguyên là định danh (identity) của đối tượng, bảo đảm duy nhất và không đổi trong suốt vòng đời đối tượng; trong CPython con số này chính là địa chỉ bộ nhớ của đối tượng, và toán tử is thực chất so sánh hai định danh đó, ví dụ a is b đúng khi id(a) == id(b). "Every object in Python doesn't have a unique id" sai vì mọi đối tượng đang tồn tại đều có định danh riêng; chỉ hai đối tượng không cùng sống một lúc mới có thể dùng lại cùng giá trị id. "None of the mentioned" sai vì đã có một phát biểu đúng về id() trong danh sách. "All of the mentioned" sai vì danh sách chứa phát biểu sai về tính duy nhất của id, nên không thể đúng tất cả.
AADD
BLEA
CNOP
DRET
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "NOP". NOP (no operation, mã máy 0x90 trên x86) chỉ tăng con trỏ lệnh EIP sang lệnh kế tiếp mà không đổi thanh ghi, cờ hay bộ nhớ nào; trong khai thác tràn bộ đệm, kẻ tấn công đặt một dải NOP dài (NOP sled) trước shellcode, nên địa chỉ trả về bị ghi đè chỉ cần rơi vào bất kỳ đâu trong dải là CPU trượt dần tới shellcode, bù cho việc không biết chính xác địa chỉ trên ngăn xếp. "ADD" cộng toán hạng nguồn vào toán hạng đích và cập nhật cờ, có tác dụng thật. "LEA" tính địa chỉ hiệu dụng rồi nạp vào thanh ghi đích, tuy không đọc bộ nhớ nhưng vẫn ghi thanh ghi. "RET" lấy địa chỉ trả về ở đỉnh ngăn xếp rồi nhảy tới đó, chính là lệnh bị lợi dụng khi ghi đè địa chỉ trả về chứ không phải lệnh đệm.
Ajz
Bamp
Cpush
Dpop
Ecall
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "push". Trên x86 32 bit theo quy ước gọi cdecl, đối số được đặt lên ngăn xếp từ phải sang trái trước lệnh gọi: chương trình push giá trị b, rồi nạp x (bằng 2) vào thanh ghi và push nó, tiếp đó push địa chỉ chuỗi định dạng, sau cùng call printf; bên trong printf đọc các đối số từ ngăn xếp ngay trên địa chỉ trả về, còn bên gọi tự cộng lại esp để dọn. Vì vậy push là lệnh đặt x vào chỗ printf tìm thấy; cần biết trình biên dịch hiện đại có thể cấp sẵn khung ngăn xếp rồi dùng mov vào [esp+…] thay cho push, và trên x64 đối số đầu nằm trong thanh ghi, nhưng câu hỏi theo mô hình cổ điển. "jz" là nhảy có điều kiện khi cờ ZF bằng 1. "amp" in sẵn như vậy và không phải lệnh x86 nào. "pop" lấy giá trị khỏi đỉnh ngăn xếp, ngược chiều cần thiết. "call" đẩy địa chỉ trả về rồi chuyển điều khiển tới printf, không đặt x.
AEAX, EBX, ECX, or EDX
BEBP or ESP
CEFLAGS
DEIP
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "EAX, EBX, ECX, or EDX". Trong x86, bốn thanh ghi này là thanh ghi đa dụng (general-purpose register) dùng chứa dữ liệu và kết quả trung gian khi tính toán như tổng tạm; EAX còn thường giữ giá trị trả về của hàm, ECX hay làm bộ đếm vòng lặp, EDX ghép với EAX trong phép nhân và phép chia. "EBP or ESP" là cặp thanh ghi ngăn xếp: ESP trỏ đỉnh ngăn xếp, EBP trỏ đáy khung ngăn xếp của hàm để truy cập biến cục bộ và tham số. "EFLAGS" chứa các cờ trạng thái như ZF, CF, SF do phép tính đặt ra, không chứa giá trị tính toán. "EIP" là con trỏ lệnh trỏ tới lệnh sắp chạy, không dùng để tính toán; mã độc chỉ nhắm vào nó khi muốn chiếm luồng thực thi.
14Which command changes the size of the stack?5 lựa chọn
Amov eax, ebx
Blea ecx, [edx+16]
Cmov ebx, [eax]
Dsub ecx, 3
Epush edx
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "push edx". Ngăn xếp (stack) trên x86 được quản lý bởi thanh ghi ESP trỏ vào đỉnh ngăn xếp; lệnh push edx giảm ESP đi 4 byte rồi ghi giá trị của edx vào ô nhớ mới tại đỉnh, nên ngăn xếp lớn thêm một phần tử (pop, call, ret hay các lệnh cộng trừ trực tiếp trên esp cũng làm đổi kích thước). Bác: "mov eax, ebx" chỉ chép giá trị giữa hai thanh ghi, ESP giữ nguyên. "lea ecx, [edx+16]" tính địa chỉ edx+16 và đặt vào ecx mà không truy cập bộ nhớ, không chạm tới ESP. "mov ebx, [eax]" đọc ô nhớ do eax trỏ tới vào ebx, chỉ là đọc dữ liệu. "sub ecx, 3" trừ 3 khỏi ecx; lệnh sub chỉ làm đổi ngăn xếp khi toán hạng đích là esp, như sub esp, 0x20 để cấp vùng biến cục bộ, còn ở đây đích là ecx nên ngăn xếp không đổi.
AThey are too large for efficient hashing
BThey are slower to access than strings
CThey can be changed in place, disrupting hashing
DThey are restricted to numerical values
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "They can be changed in place, disrupting hashing". Dictionary trong Python là bảng băm: vị trí lưu một cặp được tính từ hash(key), nên khoá phải hashable, tức giá trị băm không được đổi suốt thời gian khoá nằm trong bảng. List là kiểu khả biến (mutable), append hay gán phần tử làm nội dung đổi tại chỗ, nếu băm theo nội dung thì khoá sẽ lạc khỏi ô của nó; vì thế list không có hàm băm và dùng làm khoá sẽ ném TypeError: unhashable type: 'list', còn tuple bất biến thì dùng được. "They are too large for efficient hashing" sai vì một list rỗng cũng bị cấm, trong khi chuỗi rất dài vẫn băm được. "They are slower to access than strings" sai vì tốc độ truy cập không phải tiêu chí chọn khoá. "They are restricted to numerical values" sai vì list chứa được phần tử thuộc bất kỳ kiểu nào.
Amov
Bsub
Cnop
Dpush
Epop
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "nop". Lệnh nop (no operation, mã 0x90 trên x86) không làm gì ngoài việc chuyển sang lệnh kế tiếp. Trong tấn công tràn bộ đệm, kẻ tấn công đặt một dãy dài nop, gọi là NOP sled (đường trượt), trước shellcode: địa chỉ trả về bị ghi đè chỉ cần rơi vào đâu đó trong dãy này là CPU trượt qua các nop tới shellcode, nên không cần đoán địa chỉ chính xác. "mov" chép dữ liệu giữa thanh ghi và bộ nhớ, có trong shellcode nhưng không lặp hàng loạt. "sub" là phép trừ, đôi khi dùng để chỉnh ESP. "push" đẩy giá trị lên ngăn xếp, shellcode dùng để dựng tham số nhưng không lặp hàng trăm lần. "pop" lấy giá trị khỏi ngăn xếp, hay gặp trong chuỗi ROP chứ không phải phần đệm.
AEAX, EBX, ECX, or EDX
BEBP or ESP
CEFLAGS
DEIP
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "EFLAGS". Thanh ghi cờ EFLAGS chứa các bit trạng thái mà CPU cập nhật sau mỗi phép tính số học hay logic; cờ ZF (Zero Flag) được bật lên 1 khi kết quả của lệnh vừa thực hiện bằng 0, ví dụ sau cmp eax, ebx khi hai giá trị bằng nhau hay sau test eax, eax khi eax bằng 0, và các lệnh nhảy có điều kiện jz, jnz đọc chính cờ này để rẽ nhánh. Bác: "EAX, EBX, ECX, or EDX" là các thanh ghi đa dụng chứa toán hạng hay kết quả, bản thân chúng không báo kết quả có bằng 0 hay không. "EBP or ESP" là con trỏ khung và con trỏ đỉnh ngăn xếp, dùng để quản lý ngăn xếp. "EIP" là con trỏ lệnh, chứa địa chỉ lệnh kế tiếp sẽ được thực thi.
18A malware analyst suspects EIP manipulation. Which vulnerability type might be exploited? (Choose two)4 lựa chọn
AInteger overflow
BRace condition
CBuffer overflow
DFormat string attack
Lời giải
Mở trang câu hỏi này →Đáp án đúng gồm hai ý: "Buffer overflow" và "Format string attack". EIP là con trỏ lệnh; muốn chiếm luồng thực thi, kẻ tấn công phải ghi đè giá trị sẽ được nạp vào EIP, thường là địa chỉ trả về lưu trên ngăn xếp. Tràn bộ đệm (buffer overflow) chép dữ liệu vượt kích thước mảng cục bộ, tràn qua địa chỉ trả về, nên khi hàm thực hiện ret thì EIP nhảy tới mã của kẻ tấn công. Tấn công chuỗi định dạng (format string attack) lợi dụng printf nhận chuỗi do người dùng điều khiển, dùng %n để ghi giá trị tuỳ ý vào địa chỉ tuỳ ý như địa chỉ trả về hay một con trỏ hàm, cũng dẫn tới điều khiển EIP. Bác: "Integer overflow" là tràn số nguyên làm sai phép tính kích thước, chỉ là nguyên nhân gián tiếp có thể dẫn tới tràn bộ đệm chứ tự nó không ghi đè EIP. "Race condition" là lỗi tranh chấp thời điểm giữa các luồng hay tiến trình, khai thác thứ tự truy cập tài nguyên chứ không trực tiếp thao túng EIP.
19What type of language is bash shell script?5 lựa chọn
ALow-level languages
BLowest languages
CMachine code
DInterpreted languages
EHardware
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "Interpreted languages". Bash script là ngôn ngữ thông dịch (interpreted): trình thông dịch bash đọc từng dòng, phân tích và thực thi ngay, không biên dịch trước ra mã máy; vì vậy mã độc dạng script trên Linux đọc được trực tiếp dưới dạng văn bản. "Low-level languages" là ngôn ngữ gần phần cứng như hợp ngữ, trong khi bash là ngôn ngữ bậc cao điều khiển lệnh hệ thống. "Lowest languages" không phải một phân loại chuẩn; nếu hiểu là bậc thấp nhất thì đó là mã máy, cũng không phải bash. "Machine code" là các byte lệnh CPU chạy trực tiếp, là kết quả của biên dịch hoặc hợp dịch, không phải dạng của script. "Hardware" là phần cứng vật lý, không phải ngôn ngữ.
20Which command retrieves data from the stack?5 lựa chọn
Apush
Bcmp
Cjz
Dadd
Epop
Lời giải
Mở trang câu hỏi này →Đáp án đúng: "pop". Ngăn xếp x86 hoạt động theo kiểu vào sau ra trước; lệnh pop đọc giá trị tại đỉnh ngăn xếp, tức địa chỉ ESP đang trỏ tới, vào thanh ghi hoặc bộ nhớ đích rồi tăng ESP lên 4 byte ở chế độ 32 bit, nghĩa là lấy dữ liệu ra khỏi ngăn xếp. "push" làm ngược lại: giảm ESP rồi ghi giá trị lên đỉnh ngăn xếp. "cmp" so sánh hai toán hạng bằng một phép trừ ngầm và chỉ đặt cờ như ZF, CF, không lưu kết quả. "jz" nhảy tới địa chỉ đích khi cờ ZF bật, là lệnh rẽ nhánh chứ không đụng tới dữ liệu ngăn xếp. "add" cộng hai toán hạng và ghi kết quả vào toán hạng đích; add esp có thể bỏ dữ liệu khỏi ngăn xếp nhưng không lấy giá trị ra.