Cracker Handbook 1.0 part 217 pdf

6 150 1
Cracker Handbook 1.0 part 217 pdf

Đang tải... (xem toàn văn)

Thông tin tài liệu

Nhưng nhiệm vụ tiếp theo và rất quan trọng của chúng ta là làm cách nào để biểu đạt đoạn code dưới dạng ASM đó thành đoạn code dưới dạng cú pháp của một ngôn ngữ bậc cao (ví dụ như C). IV. Assembly code to C Bây giờ giả sử rằng tôi và các bạn có một đoạn code ASM, và chúng ta có thể đọc hiểu được nó để biết được chương trình đang làm gì.Tuy nhiên, vì hầu hết các câu lệnh ASM chỉ thực hiện một nhiệm vụ thông thường, do đó rất khó cho chúng ta biết được tổng quát nhiệm vụ của chương trình đang thực hiện cái gì. Hãy xem một đoạn mã ASM dưới đây : .004122F0: 55 push ebp .004122F1: 8BEC mov ebp,esp .004122F3: 83EC48 sub esp,048 ;"H" .004122F6: 53 push ebx .004122F7: 56 push esi .004122F8: 57 push edi .004122F9: C745F800000000 mov d,[ebp][- 08],000000000 ;" .00412300: EB09 jmps .00041230B  (1) .00412302: 8B45F8 mov eax,[ebp][-08] .00412305: 83C001 add eax,001 ;"" .00412308: 8945F8 mov [ebp][-08],eax .0041230B: 8B4508 mov eax,[ebp][08] .0041230E: 50 push eax .0041230F: FF1584A34300 call lstrlenA ;KERNEL32.dll .00412315: 3945F8 cmp [ebp][-08],eax .00412318: 7D2E jge .000412348  (2) .0041231A: 8B4508 mov eax,[ebp][08] .0041231D: 0345F8 add eax,[ebp][-08] .00412320: 8A08 mov cl,[eax] .00412322: 884DFF mov [ebp][-01],cl .00412325: 0FB645FF movzx eax,b,[ebp][-01] .00412329: 83F861 cmp eax,061 ;"a" .0041232C: 7C18 jl .000412346  (1) .0041232E: 0FB645FF movzx eax,b,[ebp][-01] .00412332: 83F87A cmp eax,07A ;"z" .00412335: 7F0F jg .000412346  (2) .00412337: 0FB645FF movzx eax,b,[ebp][-01] .0041233B: 83E820 sub eax,020 ;" " .0041233E: 8B4D08 mov ecx,[ebp][08] .00412341: 034DF8 add ecx,[ebp][-08] .00412344: 8801 mov [ecx],al .00412346: EBBA jmps .000412302  (3) .00412348: 5F pop edi .00412349: 5E pop esi .0041234A: 5B pop ebx .0041234B: 8BE5 mov esp,ebp .0041234D: 5D pop ebp .0041234E: C3 retn Bạn thấy đấy, trên đây là một đoạn mã ASM sử dụng rất nhiều các câu lệnh đơn giản kết hợp với nhau và cuối cùng là để thực hiện một nhiệm vụ nào đó mà chính chúng ta cần phải tìm hiểu. Chúng ta sẽ bắt đầu làm việc từ câu lệnh đầu tiên và cứ như thế cho đến hết, cố gắng để có một cái nhìn tổng quan nhất về những gì sẽ xảy ra bằng việc sử dụng một “Pseudo-C” notation (kí pháp Giả ngôn ngữ C), và cuối cùng là để chuyển nó về chính xác ở C code. Okie có vẻ vẫn hơi mơ hồ, tôi sẽ cùng các bạn giải quyết. Đầu tiên chúng ta sẽ bắt đầu với những dòng lệnh sau : .004122F0: 55 push ebp .004122F1: 8BEC mov ebp,esp .004122F3: 83EC48 sub esp,048 ;"H" .004122F6: 53 push ebx .004122F7: 56 push esi .004122F8: 57 push edi Hai dòng lệnh đầu tiên còn được biết đến với một cái tên là “stack frame”.Về bản chất đây là một ‘local’ stack bên trong của hàm, nơi mà chúng ta tưởng tượng như là một căn phòng đặc biệt dùng để chứa các biến cục bộ (local variables). Việc tạo ra căn phòng này có thể được thực hiện rất dễ dàng bằng cách đơn giản là giảm con trỏ stack đi một số bit nào đó, cụ thể là bao nhiêu bytes cần thiết cho việc lưu trữ các biến cục bộ. Một trong những lợi thế chính của Stack frame chính là ở thanh ghi EBP, nó có thể được sử dụng như là một con trỏ cố định tới các biến tham chiếu (reference varibales) (Nằm ở trên thanh ghi EBP là các tham số, ở dưới nó thì là các biến cục bộ) (Đọc thêm các bài viết của anh Be) Chú ý rằng các con trỏ Stack như (ESP và EBP) cần phải được phục hồi lại trước rời khỏi một hàm nào đó, để tránh cho việc lỗi Stack corruption. .004122F0: 55 push ebp .004122F1: 8BEC mov ebp,esp .004122F3: 83EC48 sub esp,048 ;"H" Trên đây là quá trình tạo Stack Frame và căn phòng được với không gian là 48 bytes dành cho việc lưu trữ các biến cục bộ. Windows yêu cầu rằng một vài thanh ghi khác ngoài ESP và EBP cũng cần được bảo vệ trong suốt quá trình của một Callback function, đó là những thanh ghi EBX, ESI và EDI. Chúng được lưu trữ một cách an toàn trên Stack, và sẵn sàng để khôi phục lại đúng vị trí trước khi rời khỏi hàm.Điều này cho phép sự tự do khi sử dụng những thanh ghi này bên trong một hàm. Đã có quá trình lưu giữ thanh ghi thì cũng phải có quá trình phục hồi chúng, điều này được thực hiện nhờ vào các câu lệnh rất đơn giản. Và nhìn vào đó ta biết ngay nó làm gì : .00412348: 5F pop edi .00412349: 5E pop esi .0041234A: 5B pop ebx .0041234B: 8BE5 mov esp,ebp .0041234D: 5D pop ebp .0041234E: C3 retn Đầu tiên 3 thanh ghi được khôi phục từ stack của chúng ta. Sau đó Stack được phục hồi lại trạng thái của nó sau khi hàm đã được gọi và khi gặp câu lệnh Return. Chú ý rằng chúng ta không thể khôi phục Stack trước khi khôi phục 3 thanh ghi được, bởi vì các thanh ghi của chúng đã được lưu trên Stack.Chuyển tất cả đoạn code trên sang C là rất dễ dàng. Bây giờ chúng ta biết rằng đây có thể là một hàm, bởi vì dựa vào Stack Frame cũng như việc lưu trữ và phục hồi các thanh ghi, v v : void SomeFunction() { //…code… } Bây giờ tôi giả sử rằng đây là một void function, bởi vì không hề có bất kì một sự thay đổi nào trong thanh ghi EAX trước khi Return. Điều đó không có nghĩa là EAX đã không bị thay đổi. Nhưng cho đến bây giờ, chúng ta sẽ giả sử giá trị trong thanh ghi EAX bị lờ đi. Tiếp theo chúng ta sẽ tiếp tục với thân của hàm này : .004122F9: C745F800000000 mov d,[ebp][- 08],000000000 ;" .00412300: EB09 jmps .00041230B  (1) .00412302: 8B45F8 mov eax,[ebp][-08] .00412305: 83C001 add eax,001 ;"" .00412308: 8945F8 mov [ebp][-08],eax .0041230B: 8B4508 mov eax,[ebp][08] .0041230E: 50 push eax .0041230F: FF1584A34300 call lstrlenA ;KERNEL32.dll .00412315: 3945F8 cmp [ebp][-08],eax .00412318: 7D2E jge .000412348  (2) Chúng ta hãy để ý tới giá trị được tham chiếu đến : d,[ebp][-08] == dword ptr[ebp-08] (in another notation) Như tôi đã nói, bời vì nó nằm dưới thanh ghi EBP của chúng ta (thanh ghi EBP đang được lưu trên Stack), vì vậy hàm đang lưu trữ một biến cục bộ ở đó. Chúng ta biết được rằng nó có kích thước là DWORD và nó có thể là một giá trị có dấu (signed value), bởi nó được đem đi so sánh với kết quả của hàm lstrlenA, mà kết quả của hàm này là một signed int). Trên nền tảng win32, thì giá trị signed dword trong C là (signed) int. Chúng ta hãy đổi tên của nó thành int_locall để cho việc đọc hiểu trở nên dễ dàng hơn : .004122F9: mov int_local1, 000000000 .00412300: jmps .00041230B  (1) .00412302: mov eax, int_local1 .00412305: add eax,001 .00412308: mov int_local1, eax .0041230B: mov eax,[ebp][08] .0041230E: push eax .0041230F: call lstrlenA ;KERNEL32.dll .00412315: cmp int_local1,eax .00412318: jge .000412348  (2) Okie đã thấy sáng sủa hơn một chút, tuy nhiên các bạn hãy cẩn thận ở đây, đừng nhầm lần giữa [ebp][08] với [ebp][-08] . Mặc dù là nhìn thoáng qua ta cũng thấy nó giống nhau đấy chứ, tuy nhiên đây lại là những địa chỉ hoàn toàn khác nhau. Biến tại địa chỉ [ebp][08] thì luôn luôn là một tham số đầu tiên được truyền vào hàm của chúng ta. Chính vì lí do đó chúng ta sẽ đổi tên của giá trị này thành dw_param1. Khà khà sau một hồi phân tích chúng ta đã xác định được biến cục bộ, và làm sáng tỏ được một số vấn đề , bây giờ chúng ta sẽ thử chuyển nó sang một đoạn mã giả C : int_local1 = 0; goto label_41230B; eax = int_local1; eax = eax + 1; int_local1 = eax; label_41230B: eax = dw_param1; eax = lstrlenA(eax); //lstrlenA returns its result in eax if( int_local1 >= eax) goto label_412348; Vậy là phần nào chúng ta đã có một cái nhìn dễ dàng hơn với đoạn code trên, tuy nhiên đây mới chỉ là điểm khởi đầu.Việc tiếp theo chúng ta phải dùng tư duy của mình để tối ưu hóa lại đoạn code này, hãy nhìn lại 3 dòng sau : eax = int_local1; eax = eax + 1; int_local1 = eax; Chúng ta sẽ thấy rằng đoạn code trên là hơi thừa nó có thể được đơn giản hóa lại như sau : int_local1++; Điểm khác biệt duy nhất giữa hai cách thể hiện này là thanh ghi EAX không xuất hiện trong cách biểu diễn thứ hai. Chúng ta cần phải cẩn thận quan sát, vì rất có thể giá trị của thanh ghi EAX sẽ lại được sử dụng ở phía bên dưới thì sao . Tiếp theo ta đến dòng kế tiếp : . .00 412 2F9: C745F 800 000 000 mov d,[ebp][- 08 ] ,00 000 000 0 ;" .00 412 300 : EB09 jmps .00 0 412 30B  (1) .00 412 302 : 8B45F8 mov eax,[ebp][ -08 ] .00 412 305 : 83C0 01 add eax ,0 01 ;"" .00 412 308 :. .00 412 2F9: mov int_local1, 00 000 000 0 .00 412 300 : jmps .00 0 412 30B  (1) .00 412 302 : mov eax, int_local1 .00 412 305 : add eax ,0 01 .00 412 308 : mov int_local1, eax .00 412 30B: mov eax,[ebp] [08 ] .00 412 30E:. C745F 800 000 000 mov d,[ebp][- 08 ] ,00 000 000 0 ;" .00 412 300 : EB09 jmps .00 0 412 30B  (1) .00 412 302 : 8B45F8 mov eax,[ebp][ -08 ] .00 412 305 : 83C0 01 add eax ,0 01 ;"" .00 412 308 : 8945F8

Ngày đăng: 03/07/2014, 17:21

Tài liệu cùng người dùng

Tài liệu liên quan